Nginx URL Encoding Issue - apache

I'm using Nginx in front of Apache and have an issue with URL encoding.
Requests for :
GET /forum/index.php%3Ftopic%3D14454.3775%3Bwap2
Produces this error in Apache (when proxy_passed from Nginx) :
/forum/index.php?topic=14454.3775;wap2' not found or unable to stat
When I request the url above (not encoded) it gets processed just fine.
The solution I found is I need to change:
proxy_pass http://127.0.0.1:80;
to
proxy_pass http://127.0.0.1:80/;
When the forward slash is excluded, the original request will not be decoded. When I add the forward slash, this is the error message I receive :
"proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block
My nginx config block is :
location ~* ^/forum/index.php
{
charset ISO-8859-1;
include /etc/nginx/proxypass.conf;
proxy_pass http://127.0.0.1:80;
}
How can I fix the proxy_pass directive and include the forward slash so the request url is decoded before it's passed over to Apache?
EDIT:
Request:
GET /index.php HTTP/1.1" 200 16481 "http://www.example.com/forum/index.php%3Ftopic%3D14454.3775%3Bwap2
Error:
script '/www/example.com/httpdocs/forum/index.php?topic=14454.3775;wap2' not found or unable to stat

I managed to solve the issue by doing this.
If there is a better way to handle this, please let me know.
location ~* /forum/index.php(.*)
{
include /nginx/proxypass.conf;
if ($args) {
proxy_pass http://127.0.0.1:80/forum/index.php?$args;
}
proxy_pass http://127.0.0.1:80/forum/index.php$1;
}

Related

Nginx -> Apache 2 authentication -> return to Nginix

We have a nginx and an apache2 server.
Apache2 is configured to manage Kerberos (Active Directory) authentication.
We have a website managed by nginx with a reserved area.
I would know if this is possible:
the user goes to main site managed by nginx
from main site, there is a link to "/login" mapped to apache2:
location /login/ {
proxy_pass http://apache2server/testlogin;
}
when the login is successful, apache2 is configured to go to another nginx webpage, using proxypass too:
ProxyPass /testlogin http://nginxserver/logindone.php
ProxyPassReverse /testlogin http://nginxserver/logindone.php
I wonder if this is the right solution to the problem.
The best way you can implement an external authentication to your NGiNX website is using auth_request directive.
Basically, you can protect any request doing a subrequest to any external web server. The subrequest must return HTTP code 2XX to allow proceeding to the content, and any other HTTP code returned will deny access.
To accomplish that, be sure you've NGiNX with auth_request enabled (compiled with --with-http_auth_request_module). To check that, use the following command at shell:
nginx -V 2>&1 | grep "http_auth_request_module"
Add the auth_request directive to the location you want to protect, specifying an internal location where the authorization subrequest will be forwarded to, using:
location /system/ {
auth_request /auth;
#...
}
So, when a request is made to /system/ location, the system will create a subrequest to /auth location. Now we need to create the internal /auth location. We can use the following example below:
location = /auth {
internal;
proxy_pass http://my.app.webserver/auth_endpoint;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
#...
}
Here, we created the /auth internal location. We used the internal directive to disable external NGiNX access (any external request to /auth will not be processed by this location). Also, we removed the request body content and set the request length to zero, removing any original request variable. We do a subrequest to http://my.app.webserver/auth_endpoint passing all requested cookies, so your backend application could determine if user has access or not.
If you need to know the original requested URI, you can add it on an extra HTTP header at subrequest adding:
proxy_set_header X-Original-URI $request_uri;
You can learn more about NGiNX auth_request directive here.

nginx proxy_pass not working in a expected way

I have front proxy as apache and back proxy as nginx. back proxy config is like below
location /my-app {
proxy_pass http://localhost:18080/my-app/;
fastcgi_intercept_errors off;
}
The problem is whenever the request sent to upstream from back proxy then double slash added
to upstream --> /my-app//myappPath
I have tried to add slash at the end of location like below to avoid double slash but back proxy not receive any request from my front proxy. so no requests to upstream application.
Please kindly help me how to avoid this double slash situation in my back proxy.
location /my-app/ {
proxy_pass http://localhost:18080/my-app/;
fastcgi_intercept_errors off;
}
You are using this directive:
proxy_pass http://localhost:18080/my-app/
Remove the "/" at the end to:
proxy_pass http://localhost:18080/my-app
That will take care of the issue.

nginx - proxy facebook/bots to a different server without changing canonical URL

TLDR;
How can I make it so that all scraper/bot requests reaching my frontend https://frontend.example.test/any/path/here are fed the data from https://backend.example.test/prerender/any/path/here without changing the canonical URL?
I have a complex situation where I have a Vue app that pulls data from a php API to render data. These are hosted in China so niceties like netlify prerender and prerender.io are not an option.
Initially I tried:
if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest\/0\.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp") {
rewrite ^/(.*)$ https://backend.example.test/prerender/$1 redirect;
}
which workd but Facebook used backend.example.text the canonical URL frontend.example.test.
Setting the og:url to the frontend app caused problems due to a redirect loop. I tried then setting the og:url to the frontend with a query param that skipped the nginx forward, but for some reason this wasn't working properly on the live server and I imagine facebook would still end up pulling the data from the final url anyhow.
Thus I imagine the only solution is to use proxy_pass but it is not permitted with a URI inside an if statement (and I have read the if is evil article).
I feel like all I need is something like a functioning version of:
location / {
if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest\/0\.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp") {
proxy_pass https://backend.example.test/prerender;
}
...
}
(I am of course aware of the contradiction of having to have Facebook sharing work in China, but the client is requesting this for their international users as well).
Here is the solution for your problem:
https://www.claudiokuenzler.com/blog/934/nginx-proper-way-different-upstream-user-agent-based-reverse-proxying-rule-without-if
I'm copying here the main parts in case the link breaks:
Create a dynamic target upstream with the map directive:
map "$http_user_agent" $targetupstream {
default http://127.0.0.1:8080;
"~^mybot" http://127.0.0.1:8090;
}
Here "~^mybot" is a regular expression, if the user agent matches that expression it will use that upstream server.
If the user-agent does not match any entries, Nginx will use the "default" entry (saving http://127.0.0.1:8080 as $targetupstream variable).
Then you just have to use a that upstream in a proxy pass setting:
location / {
include /etc/nginx/proxy.conf;
proxy_set_header X-Forwarded-Proto https;
proxy_pass $targetupstream;
}
Now, you could use one upstream pointing to locahost at a port that is being used by nginx to serve static files (for client only) and another port for the server renderer.

How to rewrite nginx path from "http://domain/api/path" to "http://domain"

I'm configuring the nginx to redirect all incoming uris which start with
/api
to the backend, this means port 1000. The issue is that the frontend path
/api/path/
becomes the backend
/
but I need it to stay the same. For example when I navigate to the backend
http://domain/api/path
I have to actually navigate to
http://domain/api/path/api/path
. Is there a possibility to rewrite the expression in order to keep the same path? The actual configuration looks like this:
location /api/ui {
include proxy_params;
proxy_pass http://localhost:1000/;
}
Thank you!

Nginx proxy_pass having problems with querystring for an API

I'm trying to proxy a certain rest endpoint on my linux api box to my windows box. Here's what I have right now.
My linux api box
...
location ~ ^/api/v0/roslyn(.*)$ {
resolver 8.8.8.8;
proxy_pass $scheme://my-windows-box.com/roslyn$1;
}
For example, I'd like to proxy the following url
http://my-linux-box.com/api/v0/roslyn?q=5
to
http://my-windows-box.com/roslyn?q=5
However, it seems to be missing the querystring, so the regex is failing?
I don't think you can match the args by regex, try this instead
location /api/v0/roslyn {
resolver 8.8.8.8;
proxy_pass $scheme://my-windows-box.com/roslyn$is_args$query_string;
}