0

I have a CentOS server running NGINX listening to 80 and a DB servering an app on 8080. I want to be able to Type

http://example.com/dev/abc

and have it actually access

http://example.com:8080/apex/abc or http://localhost:8080/apex/abc

I have used this location configuration

location /dev {
       proxy_pass http://example.com:8080/apex;
    }

However when I try it out the url displayed is

http://example.com/apex/apex

the page is not found and the log says:

2018/06/14 12:51:33 [error] 7209#0: *2067 open()
"/usr/share/nginx/html/apex/apex" failed (2: No such file or directory), 
client: 124.157.113.187, server: _, request: "GET /apex/apex HTTP/1.1", host: "example.com"

Looks like two strange things are happening

1) Port 80 not 8080 is being used despite the proxy_pass

2) why is apex twice "/apex/apex/"

Help please :)

Adding entire Server block from config file:

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  example.com;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

   location /dev {
       proxy_pass http://example.com:8080/apex;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

Update - More information on what the app that might help

The app is Oracle Application Express (APEX) it listens on port 8080. The URL works as follows:

HTTP://example.com:8080/apex/f?p=[APP]:[Page]:[Session] etc

Where [APP],[Page] and [Session] are all corrisponding numbers

The development environment url is actualy:

http://example.com:8080/apex/f?p=4550

This is the default so if I try http://example.com:8080/apex/ it defaults to http://example.com:8080/apex/f?p=4550 and takes you to the login page

Everything after the app number never changes so that is what I want to replaced by /dev/ http://example.com:8080/apex/f?p=4550:1 -> http://example.com/dev/:1

Once I have leant how this works, I plan to setup three proxy_pass's

example.com/dev -> http://example.com:8080/apex/f?p=4550

example.com/desktop -> http://example.com:8080/apex/f?p=1001

example.com/mobile -> http://example.com:8080/apex/f?p=201

Where the only thing that changes is the app number.

Rewrites are working fine for all three but I don't want the rewrite to be visible in the URL

Here are the rewrites:

   location ~ /dev {
       rewrite ^/dev(.*) http://smallblockpro.com:8080/apex$1 last;
    }
   location ~ /desktop/ {
       rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
    }

    location ~ /desktop {
       rewrite ^/desktop(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
    }

    location ~ /mobile/ {
       rewrite ^/mobile/(.*) http://smallblockpro.com:8080/apex/f?p=201:$1 last;
    }

    location ~ /mobile {
       rewrite ^/mobile(.*) http://smallblockpro.com:8080/apex/f?p=201:$1 last;
    }
cnst
  • 25,870
  • 6
  • 90
  • 122
AndrewT
  • 468
  • 1
  • 8
  • 23
  • 1
    use listen 80; server_name example.com;location /dev {proxy_pass http://example.com:8080/apec;} – Se Song Jun 14 '18 at 03:03
  • Thanks but didn't fix it I did not have the server_name part put it still drops the :8080 and adds an extra apex/ i.e. example.com/apex/apex I will put up the entire server block in case there is an issue elsewhere. – AndrewT Jun 14 '18 at 23:46
  • Well that was disapointing, spent hours on it, tried everything suggested, didn't get solved but still lost the bounty. Then it looks like everyone who tried came in and down voted my question no reason given why. Even had someone use it to try and get work. Will assign the bounty to Kris as he made the most effort to help. – AndrewT Jun 24 '18 at 21:39
  • @AndrewT, you cannot solve a problem to the spec when you don't have a spec. Your question requires advanced knowledge of both nginx (to write the config) and Oracle ApEx (to understand how it works and come up with the spec for nginx). It's hardly a surprise you couldn't get a solution and got downvoted, TBH, because you were asking for an nginx config, but couldn't explain in the pseudocode the actions that such config must account for. – cnst Jun 25 '18 at 17:29
  • @cnst if I had the said knowlegde I would not be asking the question. What I am trying to do I had thought was not unusual to use NGINX or apache to map urls to Apex which is used for millions of internet apps. I hoped someone who had done this before might be able to help, I wasn't expecting someone to build somthing based on my design spec. I made many updates and tried all suggestions multiple times a day to do my part becuase yes I don't have the knowlegde to do it myself. I even upvoted your comment when you worked out part of the issue was at the app end. I did my best – AndrewT Jun 25 '18 at 21:10
  • Thanks everyone for your help, when I eventually solve this I will come back and update it for the next person. – AndrewT Jun 25 '18 at 21:11
  • @AndrewT, comment upvotes mean nothing; I actually solved a big part of your question — indeed, addressing the title of the question — and didn't even get an upvote for that; upvoting the comments is meaningless. StackOverflow is not intended to be a complete replacement for solving very complex issues on interaction of multiple independent components. I'm willing to bet the intersection of people who know both Oracle AND nginx is rather small in the real world as well, so, you effectively lost the bounty the minute you decided that someone HAS to know both, which wasn't the case. – cnst Jun 25 '18 at 21:59
  • @cnst actually they do mean somthing "this comment adds somthing useful to your post" which it did. As I said before thank you for your help. – AndrewT Jun 25 '18 at 22:12
  • @AndrewT, I don't know if you're for real or not, but if you truly want to thank me for my help, maybe upvote the actual answer? After all, it did help you get rid of the port number, didn't it? The only reason it doesn't do everything you ever wanted is because the question is lacking a spec of how APEX works. – cnst Jun 26 '18 at 00:49
  • No it did not get rid of the port number becuase I could not use any of your suggestion as it caused an error every time just as I said in the comments at the time "to many redirects" (you never responded) I rolled back all of it to get my project working again. I am finished with this conversation. – AndrewT Jun 26 '18 at 01:08

3 Answers3

0
location ~ /desktop/ {
    rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;
 }

The reason you're getting the :8080 port number shown up to the user is because you use absolute URLs in your rewrite directives, which results in NGINX producing 301 Moved responses directly to the user — your presumed expectation that it'll still go through proxy_pass after a rewrite like that is incorrect, see http://nginx.org/r/rewrite:

If a replacement string starts with “http://”, “https://”, or “$scheme”, the processing stops and the redirect is returned to a client.

If you want to just create the mapping between /desktop/$1 on the front-end and /apex/f?p=1001:$1 on the back-end of your Oracle Application Express (APEX), then the best way would be to use the following code on your nginx front-end server:

location /desktop/ {
    rewrite ^/desktop/?(.*)$ /apex/f?p=1001:$1 break;
    return 400;
    proxy_pass http://smallblockpro.com:8080;
}

I would recommend copy-pasting it for each of /dev/, /mobile/ and /desktop/; also, I would not recommend to keep a slash-less versions, as per ServerFault's nginx-reverse-proxy-url-rewrite and how-to-remove-the-path-with-an-nginx-proxy-pass, as nginx already takes care of the requests without the trailing slash in a situation such as yours with the code as I propose above.

cnst
  • 25,870
  • 6
  • 90
  • 122
  • Progress but not working, it shows a url that should work http://smallblockpro.com/foo/f?p=1001:1:::::: but then it must loop through again and tries to find page 'F' meaning it must grab the 'f' from f?p and map it to http://smallblockpro.com/foo/f?p=1001:f which is invalid. Progress is that 8080 and apex has been mapped. – AndrewT Jun 21 '18 at 20:14
  • 1
    @AndrewT Have you tried putting `f` into the rewrite, then? You can use `f?` for an optional f, as in, `rewrite ^/desktop/?f?(.*)$ /apex/f?p=1001:$1 break;`. – cnst Jun 21 '18 at 22:20
  • The '?' as optional is helpful but its more than 'f' that is optional and should be matched. I tried this: location /foo/ { rewrite ^/foo/?(f?p=1001:)?(.*)$ /apex/f?p=1001:$1 break; #rewrite ^/foo/?(.*)$ /apex/f?p=1001:$1 break; return 400; proxy_pass http://smallblockpro.com:8080; } But getting error too many redirects and url is showing http://smallblockpro.com/foo/f?p=1001:1:::::: not http://smallblockpro.com/foo/1::::: – AndrewT Jun 21 '18 at 23:57
0

Here's the copy-paste from what I'm using on our ORDS / SDW ( sqldev-web ) development server.

Here's a basic example with ORDS for the REST side of the house.

The access is to:

 https://xyz.oraclecorp.com/sdw/klrice/metadata-catalog/

Then it's proxied to:

 https://xyz.oraclecorp.com:8083/ords/klrice/metadata-catalog/

With this config. Beside not to rewrite to an absolute URI as that will do a full browser redirect vs just rewriting the url for the proxy pass.

   location /sdw/ {
       rewrite /sdw/(.*) /ords/$1 break;
       proxy_pass https://xyz.oraclecorp.com:8083/ords/;
       proxy_redirect    off;
       proxy_set_header  Host             $http_host;
       proxy_set_header  X-Real-IP        $remote_addr;
       proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;

    }

The issue you will face is this

   rewrite ^/desktop/(.*) http://smallblockpro.com:8080/apex/f?p=1001:$1 last;

APEX will see and write links/redirects/includes ( javascript/css/...) as the .../apex/XYZ which will hit the nginx server and that will not know what to do with a /apex/

Here's an example of that based on my above setup. Notice my request to /sdw/ turns into a Location redirect to /ords/

 wget  -S https://xyz.oraclecorp.com/sdw/
--2018-06-21 17:10:28--  https://xyz.oraclecorp.com/sdw/
Resolving xyz.oraclecorp.com... 123.456.789.123
Connecting to xyz.oraclecorp.com|123.456.789.123|:443... connected.
HTTP request sent, awaiting response... 
  HTTP/1.1 302 Found
  Server: nginx/1.12.1


  Location: https://xyz.oraclecorp.com/ords/f?p=4550:1:375440000433:::::
Location: https://xyz.oraclecorp.com/ords/f?p=4550:1:375440000433::::: [following]

So the easiest thing to do is match up the ords deployment ( /apex/ ) to what the rewrite/redirects are and use proxy pass to internalize the :8080 stuff. So

location ~ /desktop/ {
       rewrite ^/desktop/(.*) http://smallblockpro.com/apex/f?p=1001:$1 last;
    }
location ~ /apex/ {
       proxy_pass http://smallblockpro.com:8080/apex/;
       proxy_redirect    off;
       proxy_set_header  Host             $http_host;
       proxy_set_header  X-Real-IP        $remote_addr;
       proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    }

This option will let your users have a nice entry point of /desktop/ but then that redirect the /apex/ for the app itself.

There is another option with ORDS url-mappings.xml to keep the /desktop/ also which would be something like this to add in mappings to ords so it knows the /desktop/. Then the nginx could do the same proxy pass for each of the entry urls.

url-mapping.xml file contents

 <pool-config xmlns="http://xmlns.oracle.com/apex/pool-config">
    <pool name="mypool" base-path="/desktop" />
   </pool-config>

then in nginx

location ~ /desktop/ {
       proxy_pass http://smallblockpro.com:8080/desktop/;
       proxy_redirect    off;
       proxy_set_header  Host             $http_host;
       proxy_set_header  X-Real-IP        $remote_addr;
       proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
    }
Kris Rice
  • 3,300
  • 15
  • 33
  • Sorry Kris i din't really understand this from what I can see you are doing a port and uri change so similar. why is /ords/ in the rewrite and proxy_pass that is different to all other examples. – AndrewT Jun 21 '18 at 20:32
  • 1
    I see you added to the question. Nice URLs for apex is the goal – Kris Rice Jun 21 '18 at 20:41
  • Yes but not over the top just want to hide :8080/apex/f?p=1001: page/ session etc will follow so http://smallblockpro.com:8080/apex/f?p=1001:1:132886511937::::: will look like http://smallblockpro.com/desktop/1:132886511937::::: /desktop/ will always be replaced by ':8080/apex/f?p=1001:' in the back – AndrewT Jun 21 '18 at 21:17
  • Tried your first option: location ~ /desktop/ { rewrite ^/desktop/(.*) http://smallblockpro.com/apex/f?p=1001:$1 last; } location ~ /apex/ { proxy_pass http://smallblockpro.com:8080/apex/; proxy_redirect off; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } this does not retain the url (I think you were saying that) I already had that working in my origonal question with just a rewrite. – AndrewT Jun 22 '18 at 00:19
  • Trying the mypool option now – AndrewT Jun 22 '18 at 00:19
  • Is ORDS part of NGINX and where do I find url-mapping.xml?Or is it part of the DB, note I am using Oracle 11g Express addition. – AndrewT Jun 22 '18 at 00:22
  • it's oracle.com/rest which is for apex/rest w/oracle db. – Kris Rice Jun 22 '18 at 00:44
  • Can't find that file on the server (url-mapping.xml) may not be part of 11g Express addition. I will do some more googling on it – AndrewT Jun 22 '18 at 01:05
  • Sorry I am lost, feels like I am getting deeper into the rabit hole with less and less knowledge. Cant find the file you suggest on the apex server anywhere. Just using the default listner that comes with Apex Express. Unless you know how I can make the suggested changes I will have to give up on this lead :( – AndrewT Jun 22 '18 at 01:31
  • Read this. Best way to run apex is with ords over the embedded plsql gateway which sounds like what you are doing. https://joelkallman.blogspot.com/2017/05/apex-and-ords-up-and-running-in2-steps.html – Kris Rice Jun 22 '18 at 01:34
  • Had a read, changing the listener is to much of a change to test out your idea, I only have one environment and it took some time getting everything working. I am looking for a solution in NGINX or firwalld or Apex in the GUI. I am starting to think it is not possible. – AndrewT Jun 22 '18 at 04:37
-1

Before you read further go through below SO thread which explains about the extra /apex/

Nginx proxy_pass only works partially

Two issues in your config

  1. You need to pass the correct URL to backend service
  2. You need to make sure you handle any redirects and replace the url correctly

Below is the config I think should work for you

server {
    listen       80 default_server;
    listen       [::]:80 default_server;
    server_name  example.com;
    root         /usr/share/nginx/html;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

   location /dev/ {
       proxy_pass http://example.com:8080/apex/;
       proxy_redirect http://example.com:8080/apex/ $scheme://$host/dev/;
    }

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}
Tarun Lalwani
  • 142,312
  • 9
  • 204
  • 265
  • Code example did not work. When trying http://example.com/dev "Failed no such file or directory" when I try http://example.com/dev/ is says no resolver defined ... – AndrewT Jun 18 '18 at 20:20
  • Will do the reading you suggested and also the proxy_redirect which I have never heard of before and fiddle a bit more. – AndrewT Jun 18 '18 at 20:27
  • Will try that now – AndrewT Jun 18 '18 at 20:29
  • Still looking for /apex/apex on wrong port in url also tried curl command: curl -i http://example.com/foo HTTP/1.1 301 Moved Permanently Server: nginx/1.12.2 Date: Tue, 19 Jun 2018 00:40:48 GMT Content-Type: text/html Content-Length: 185 Location: http://example.com/foo/ Connection: keep-alive 301 Moved Permanently

    301 Moved Permanently


    nginx/1.12.2
    – AndrewT Jun 19 '18 at 00:43
  • Log file says: 2018/06/19 12:58:26 [error] 11943#0: *3509 open() "/usr/share/nginx/html/apex/apex" failed (2: No such file or directory), client: 124.157.113.155, server: example.com, request: "GET /apex/apex HTTP/1.1", host: "example.com" – AndrewT Jun 19 '18 at 01:01
  • 1
    @AndrewT, the problem is happening on the main url itself or in assets its loading? Your app is making a redirect for some reason which is causing the problem here – Tarun Lalwani Jun 19 '18 at 04:05
  • I will update the question to include more about what the app does with /apex/ to see if this helps. But the logs look to me like it never goes to the app and instead is looking for html in a folder. – AndrewT Jun 19 '18 at 04:12