Melayani beberapa titik akhir proxy di bawah lokasi di Nginx

13

Saya memiliki beberapa titik akhir API yang ingin saya layani di bawah satu lokasi /apidengan subpath yang menuju ke titik akhir yang berbeda. Secara khusus, saya ingin webdis tersedia di /apidan API eksklusif tersedia di /api/mypath.

Saya tidak khawatir tentang bentrokan dengan API webdis karena saya menggunakan subpath yang tidak mungkin berbenturan dengan nama perintah redis, dan juga memiliki kontrol penuh atas desain API untuk menghindari bentrokan.

Ini file konfigurasi dari server pengujian saya yang telah saya peretas:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # temporary hardcoded workaround
  location = /api/mypath/about {
    proxy_pass http://localhost:3936/v1/about;
  }

  location /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }

  # tried this but it gives "not found" error
  #location ^~ /api/mypath/ {
  #  rewrite ^/api/mypath/(.*)$ /$1 break;
  #  proxy_pass http://localhost:3936/v1/;
  #}
  #
  #location ^~ /api {
  #  rewrite ^/api/(.*)$ /$1 break;
  #  proxy_pass http://localhost:7379/;
  #}
}

Bagaimana saya bisa mengubah solusi saya sehingga setiap permintaan untuk /api/mypath/*pergi ke titik akhir di port 3936, dan yang lainnya ke port 7379?

hamstar
sumber
Apa maksudmu tried this to no avail? Apa yang terjadi ketika Anda mengaktifkan arahan lokasi itu? Waktu koneksi habis? Lokasi tidak cocok?
masegaloeh
Ah terima kasih atas promptnya, ini memberikan kesalahan yang tidak ditemukan, pada penyelidikan lebih lanjut tampaknya kesalahan tersebut berasal dari API saya sehingga berfungsi! : D Tetapi aturan penulisan ulang jelas bukan karena saya harus menambahkan v1 ke URL ( localhost / api / mypath / v1 / about ) ... :(
hamstar

Jawaban:

23

Anda tidak perlu menulis ulang untuk ini.

server {
  ...

  location ^~ /api/ {
    proxy_pass http://localhost:7379/;
  }
  location ^~ /api/mypath/ {
    proxy_pass http://localhost:3936/v1/;
  }
}

Menurut dokumentasi nginx

Lokasi dapat ditentukan oleh string awalan, atau dengan ekspresi reguler. Ekspresi reguler ditentukan dengan ~*pengubah sebelumnya (untuk pencocokan case-sensitive), atau ~pengubah (untuk pencocokan case-sensitive). Untuk menemukan lokasi yang cocok dengan permintaan yang diberikan, nginx pertama memeriksa lokasi yang ditentukan menggunakan string awalan (lokasi awalan). Di antara mereka, lokasi dengan awalan pencocokan terpanjang dipilih dan diingat. Kemudian ekspresi reguler diperiksa, sesuai urutan kemunculannya di file konfigurasi. Pencarian ekspresi reguler berakhir pada kecocokan pertama, dan konfigurasi yang sesuai digunakan. Jika tidak ditemukan kecocokan dengan ekspresi reguler maka konfigurasi lokasi awalan yang diingat sebelumnya digunakan.

Jika lokasi awalan pencocokan terpanjang memiliki ^~pengubah maka ekspresi reguler tidak dicentang.

Karenanya setiap permintaan yang dimulai dengan /api/mypath/akan selalu dilayani oleh blok kedua karena itu adalah lokasi awalan yang paling cocok .

Setiap permintaan yang dimulai dengan /api/tidak segera diikuti mypath/akan selalu dilayani oleh blok pertama, karena blok kedua tidak cocok, oleh karena itu menjadikan blok pertama lokasi awalan yang paling cocok .

Alexey Ten
sumber
2
Jika Anda melihat pengubah lokasi ( =, ~*, ~, dan ^~) itu mungkin tampak kontra-intuitif yang ^~tidak termasuk ekspresi reguler (karena ~menunjukkan pertandingan ekspresi reguler) ... Namun, jika Anda ingat, ^di dalam kelas karakter regex (misalnya [^a-z]) meniadakan bahwa kelas (seperti contohnya berarti (karakter apa pun kecuali yang dari az); demikian pula, ^~meniadakan setiap blok lokasi ekspresi reguler yang potensial.
Doktor J
6

OK menemukan jawabannya, saya pikir kesalahan "tidak ditemukan" berasal dari nginx, tetapi sebenarnya itu berasal dari API saya. Ini solusi saya jika ada yang tertarik:

server {
  listen 80;
  server_name localhost;
  server_name 192.168.3.90;
  server_name 127.0.0.1;

  location / {
    root /home/me/src/phoenix/ui;
    index index.html;
  }

  # automatically go to v1 of the (grape) API
  location ^~ /api/mypath/ {
    rewrite ^/api/mypath/(.*)$ /v1/$1 break;
    proxy_pass http://localhost:3936/;
  }

  location ^~ /api {
    rewrite ^/api/(.*)$ /$1 break;
    proxy_pass http://localhost:7379/;
  }
}
hamstar
sumber