Home > front end >  How to redirect API calls with nginx?
How to redirect API calls with nginx?

Time:09-23

Using nginx I am trying to redirect API calls to an external API provider website but after a lot of research and tries I feel I miss something important.

For example, my goal is when I open https://mywebsite/api/somedata, then a remote API provider is called https://api-somewebsite.com/somedata.

My basic try was:

location /api/ {
   proxy_pass https://api-somewebsite.com/;
}

I added a log format to try to get more informations:

log_format upstreamlog '[$time_local] $remote_addr - $remote_user - $server_name $host to: $upstream_addr: $request $status upstream_response_time $upstream_response_time msec $msec request_time $request_time';

Then used it to log the calls:

location /api/ {
    proxy_pass https://api-somewebsite.com/;
    access_log /var/log/nginx/upstream.log upstreamlog;
}

And it seems that the /api/ part is not well removed:

[21/Sep/2022:11:23:17 -0400] 88.163.105.196 - - - mywebsite.com mywebsite.com to: xxx.xx.xx.xx:xxx, xxx.xx.xx.xx:xxx: GET /api/somedata HTTP/1.1 502 upstream_response_time 0.005, 0.008 msec 1663773797.354 request_time 0.012

So basically it seems to call https://api-somewebsite.com/àpi/somedata which does not exist and thus return 502 error.

I have read that with the trailing / the /api/ part should be well removed automatically. But it does not work. So I tried to rewrite it by myself:

location /api/ {
    proxy_pass https://api-somewebsite.com/;
    access_log /var/log/nginx/upstream.log upstreamlog;
    rewrite ^/api/(.*) /$1 break;
}

Still no luck.

I ended up trying some stuff found on the web but that I do not fully understand... like adding proxy_redirect instruction:

location /api/ {
    proxy_pass https://api-somewebsite.com/;
    access_log /var/log/nginx/upstream.log upstreamlog;
    rewrite ^/api/(.*) /$1 break;
    proxy_redirect  https://api-somewebsite.com/ /api/;
}

Well, I feel that I lack some basic stuff to make it work, but I cannot find what. Any insights would be greatly appreciated.

====== EDIT 1 ======

According to Stephen Dunne answer, i tried to add an upstream for the server. Here is my edited code:

upstream magiceden {
    server api-mainnet.magiceden.dev:443 max_fails=0; 
    zone magiceden-api 64k;
    keepalive 60;
}

server {
    server_name genoverse.me www.genoverse.me;

    location / {
        root /home/hcomere/genoverse.me;
        index index.html;
    }
    
    location /magiceden_api/ {
        proxy_pass https://magiceden/;
        access_log /var/log/nginx/access_magiceden.log upstreamlog;
    }

    listen [::]:443 ssl; # managed by Certbot
    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/genoverse.me/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/genoverse.me/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}

I still have error 502 - Bad Gateway - when visiting https://www.genoverse.me/magiceden_api/ where i should get an error 400 - Not found - from the api provider https://api-mainnet.magiceden.dev/

====== EDIT 2 ======

Oh well, i discovered that browsers have a redirect cache, this explain why sometimes things did not work where they should work. Once i cleared the redirect cache after each config modification, things were way more smooth and understandable !...

CodePudding user response:

I think the issue here is that you are using a Uri and not an upstream.

I have read that with the trailing / the /api/ part should be well removed automatically.

This is correct.

Try adding an upstream for the server.

upstream somesite {
    server api-somewebsite.com:443 max_fails=0; 
    zone somesite-api 64k;
    keepalive 60;
}

And then use the upstream in your location block (keeping the trailing slash)

location /api/ {
    proxy_pass https://somesite/;
    access_log /var/log/nginx/upstream.log upstreamlog;
}

Now when you browse to the /api location you should be redirected as expected.

  • Related