Чи можуть блоки розташування nginx відповідати рядку запиту URL-адреси?


23

Чи можуть nginx locationблоки відповідати рядку запиту URL-адреси?

Наприклад, який блок розташування може відповідати GETзапиту HTTP

GET /git/sample-repository/info/refs?service=git-receive-pack HTTP/1.1

Я б здогадувався, що "location / git / sample-repository / info / refs? Service = git-accept-pack", оскільки nginx просто порівнює рядки.
JosefScript

Порівняння рядків всієї URL-адреси або лише частини перед знаком питання ( ?)?
Дерек Махар



1
Дещо останнє уточнення, коли я сам наткнувся на цю проблему: nginx.org/en/docs/http/request_processing.html чітко зазначає: "Зауважте, що локації всіх типів перевіряють лише частину URI-рядка запиту без аргументів. Це робиться тому, що аргументи у рядку запиту може бути задано декілька способів "
Thomas Urban

Відповіді:


37

Чи можуть блоки розташування nginx відповідати рядку запиту URL-адреси?

Коротка відповідь : Ні.

Довга відповідь : Існує рішення, якщо у нас є лише кілька таких блоків розташування.

Ось зразок вирішення для трьох блоків розташування, які повинні відповідати конкретним рядкам запитів:

server {
  #... common definitions such as server, root

  location / {
    error_page 418 = @queryone;
    error_page 419 = @querytwo;
    error_page 420 = @querythree;

    if ( $query_string = "service=git-receive-pack" ) { return 418; }
    if ( $args ~ "service=git-upload-pack" ) { return 419; }
    if ( $arg_somerandomfield = "somerandomvaluetomatch" ) { return 420; }

    # do the remaining stuff
    # ex: try_files $uri =404;

  }

  location @queryone {
    # do stuff when queryone matches
  }

  location @querytwo {
    # do stuff when querytwo matches
  }

  location @querythree {
    # do stuff when querythree matches
  }
}

Ви можете використовувати $ query_string, $ args або $ arg_fieldname. Усі зроблять роботу. Ви можете дізнатися більше про сторінку помилок в офіційних документах .

Попередження: Будь ласка, не використовуйте стандартні коди HTTP .


1
Цікавий підхід! Чи можу я рекомендувати $args ~ "service=git-send-pack"замість $args = "service=git-send-pack"? Ця форма вміщує кілька параметрів запиту.
Дерек Махар

1
stackoverflow.com/a/40313590/107158 ілюструє підхід, який я дотримувався для обробки рядкових аргументів запитів. Як і ваша відповідь, моя використовує ifі $arg_fieldname, але використовує rewriteзамість error_pageі location @name. Зауважте, що в цьому прикладі мої спроби використання @nameдля параметра заміни в не rewriteбули успішними.
Дерек Махар

1
До речі, вона повинна бути $args ~і $arg_somerandomfield =.
Дерек Махар

1
Для цього також можна використовувати mapфункцію nginx , яка швидше.
Tero Kilkanen

1
@PothiKalimuthu, дякую за уточнення цього. Те , що я зробив у цей час, щоб замінити queryпараметр з допомогою URL - шлях один , як це feedback/{auth_key}замість /feedback?auth_key=abc. Таким чином мені не потрібно використовувати if, я можу визначити шаблон розташування за допомогою, regexі це все.
WM

4

Мені відомо, що це питання вже понад рік, але я останні кілька днів руйнував мій мозок через подібну проблему. Мені хотілося різних правил аутентифікації та поводження з публічними та приватними репортажами, включаючи натискання та витягування. Це я нарешті придумав, тому я подумав, що поділюсь. Я знаю if, це хитра директива, але це, здається, працює для мене просто чудово:

# pattern for all repos, public or private, followed by username and reponame
location ~ ^(?:\/(private))?\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?$ {

    # if this is a pull request
    if ( $arg_service = "git-upload-pack" ) {

        # rewrite url with a prefix
        rewrite ^ /upload$uri;

    }

    # if this is a push request
    if ( $arg_service = "git-receive-pack" ) {

        # rewrite url with a prefix
        rewrite ^ /receive$uri;

    }

}

# for pulling public repos
location ~ ^\/upload(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pushing public repos
location ~ ^\/receive(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pulling private repos
location ~ ^\/upload\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}

# for pushing private repos
location ~ ^\/receive\/private(\/([A-Za-z0-9]+)\/([A-Za-z0-9]+)\.git(\/.*)?)$ {

    # auth_basic "git";
    # ^ if you want

    # ...
    # fastcgi_pass unix:/var/run/fcgiwrap.socket;
    # ...

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.