# How to process only first path element in the URL as the CGI executable

**URL:** <https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216>\
**Category:** NGINX\
**Created:** [October 8, 2010, 5:04pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216 "2010-10-08T17:04:16Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 8, 2010, 5:04pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/1 "2010-10-08T17:04:16Z")

</div>

I am using a FreePascal web module designed for apache cgi-bin with  
nginx.

The CGI itself is called spidersample.cgi and contains modules such as  
hello, bye etc.

With Apache when spidersample.cgi/hello is called, spidersample.cgi gets  
executed, and passes control to the hello subroutine it contains.

With nginx instead of executing spidersample.cgi it treats  
spidersample.cgi/hello as meaning a hello file in a spidersample.cgi  
directory, and returns with a 404 error as there is no such directory.

I suspect it is an easily fixed problem with some rewrite rules in the  
configuration file and it is posted below.

=============================================

server {  
listen 8118;  
server\_name localhost;  
access\_log /var/log/nginx/sysman\_access.log;  
index index.html;  
root /home/rchurch/Data/Lazarus/CgiApps;

```
    location ~ \.cgi$ {
            include /etc/nginx/fastcgi_params;
            fastcgi_pass unix:/tmp/sysman_cgi.sock;
            fastcgi_param SCRIPT_FILENAME

```

$document\_root$fastcgi\_script\_n$  
fastcgi\_param QUERY\_STRING $query\_string;  
fastcgi\_param REQUEST\_METHOD $request\_method;  
fastcgi\_param CONTENT\_TYPE $content\_type;  
fastcgi\_param CONTENT\_LENGTH $content\_length;  
}  
}

==================================================================

–  
Frank C.

=======================  
[http://devblog.brahmancreations.com](http://devblog.brahmancreations.com)

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 8, 2010, 5:56pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/2 "2010-10-08T17:56:57Z")

</div>

On Fri, Oct 08, 2010 at 04:02:48PM +0100, Frank C. wrote:

Hi there,

> With Apache when spidersample.cgi/hello is called, spidersample.cgi gets  
> executed, and passes control to the hello subroutine it contains.

That’ll be due to the way Apache is configured.

> With nginx instead of executing spidersample.cgi

nginx doesn’t execute cgi programs. It usually is configured either to  
proxy\_pass the request to a http server that will, or to fastcgi\_pass  
with params to a fastcgi-processing server.

It might just be a terminology difference, or it might be important to  
your image of what happens.

> it treats  
> spidersample.cgi/hello as meaning a hello file in a spidersample.cgi  
> directory, and returns with a 404 error as there is no such directory.

That’s probably down to the (default) configuration.

> ```
> location ~ \.cgi$ {
> 
> ```

That says “for any request that ends in the four characters ‘.cgi’,  
use this config”.

Your request for “/spidersample.cgi/hello” doesn’t match, and so doesn’t  
use this config.

For initial testing, if you remove the “$”, then the config will be  
used for any request that includes the 4-char string “.cgi”. That should  
allow you to confirm the rest of the configuration.

Then you can change the location definition to include all and only the  
requests you want handled this way.

Good luck with it,

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 8, 2010, 6:05pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/3 "2010-10-08T18:05:08Z")

</div>

On 8 Out 2010 16h02 WEST, [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> server {  
> listen 8118;  
> server\_name localhost;  
> access\_log /var/log/nginx/sysman\_access.log;  
> index index.html;  
> root /home/rchurch/Data/Lazarus/CgiApps;
> 
> location ~ .cgi$ {  
> include /etc/nginx/fastcgi\_params;  
> fastcgi\_pass unix:/tmp/sysman\_cgi.sock;  
> fastcgi\_param SCRIPT\_FILENAME $document\_root$fastcgi\_script\_n$

Try: fastcgi\_param SCRIPT\_FILENAME $document\_root$fastcgi\_script\_name;

— appa

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 8, 2010, 10:11pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/4 "2010-10-08T22:11:00Z")

</div>

On 8 October 2010 16:59, AntÃ³nio P. P. Almeida [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > # gets executed, and passes control to the hello subroutine it
> > 
> > fastcgi\_pass unix:/tmp/sysman\_cgi.sock;  
> > fastcgi\_param SCRIPT\_FILENAME $document\_root$fastcgi\_script\_n$
> 
> Try: fastcgi\_param SCRIPT\_FILENAME $document\_root$fastcgi\_script\_name;

That is due to a cut and paste issue from a narrow terminal screen, the  
real  
line is just as yours.

> — appa
> 
> * * *
> 
> nginx mailing list  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [mailman.nginx.org archive](http://nginx.org/mailman/listinfo/nginx)

–  
Frank C.

=======================  
[http://devblog.brahmancreations.com](http://devblog.brahmancreations.com)

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 8, 2010, 10:11pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/5 "2010-10-08T22:11:35Z")

</div>

On 8 October 2010 16:55, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> For initial testing, if you remove the “$”, then the config will be  
> used for any request that includes the 4-char string “.cgi”. That should  
> allow you to confirm the rest of the configuration.

I removed the “$” and now this is the error message I get:

2010/10/08 21:06:46 [error] 14628#0: \*22 FastCGI sent in stderr: “Cannot  
chdir to script directory  
(/home/rchurch/Data/Lazarus/CgiApps/spidersample.cgi)” while reading  
response header from upstream, client: 127.0.0.1, server: localhost,  
request: “GET /spidersample.cgi/hello HTTP/1.1”, upstream:  
“fastcgi://unix:/tmp/rchurch\_cgi.sock:”, host: “localhost:8118”,  
referrer: "  
[http://localhost:8118/spidersample.cgi](http://localhost:8118/spidersample.cgi)"

> nginx mailing list  
> [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> [mailman.nginx.org archive](http://nginx.org/mailman/listinfo/nginx)

–  
Frank C.

=======================  
[http://devblog.brahmancreations.com](http://devblog.brahmancreations.com)

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 10, 2010, 3:42am UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/6 "2010-10-10T03:42:36Z")

</div>

On 8 Out 2010 16h02 WEST, [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> [1 \<multipart/alternative (7bit)\>] [1.1 \<text/plain; ISO-8859-1  
> (7bit)\>] I am using a FreePascal web module designed for apache  
> cgi-bin with nginx.
> 
> The CGI itself is called spidersample.cgi and contains modules such  
> as hello, bye etc.
> 
> With Apache when spidersample.cgi/hello is called, spidersample.cgi  
> gets executed, and passes control to the hello subroutine it  
> contains.

Isn’t there something missing here? I would expect for a query string  
separator somewhere that signals the application data portion of the  
URI. It should be a ‘?’, according to

> **[RFC 3986: Uniform Resource Identifier (URI): Generic Syntax | RFC Editor](https://www.rfc-editor.org/info/rfc3986/)**
>
> A Uniform Resource Identifier (URI) is a compact sequence of characters that identifies an abstract or physical resource. This specification defines the generic URI syntax and a process for resolving URI references that might be in relative form,...

Something like spidersample.cgi?q=hello or similar.

I’m guessing that there’s some rewrite rule in the Apache config that  
didn’t get converted to nginx. Hence the script is failing. And it  
makes sense according to the config. After all any request not ending  
in .cgi is handled “as usual” by nginx, therefore it tries to get the  
file in /home/rchurch/Data/Lazarus/CgiApps/spidersample.cgi/hello. If  
it doesn’t exist it returns a 404.

> With nginx instead of executing spidersample.cgi it treats  
> spidersample.cgi/hello as meaning a hello file in a spidersample.cgi  
> directory, and returns with a 404 error as there is no such  
> directory.

Yes.

> I suspect it is an easily fixed problem with some rewrite rules in  
> the configuration file and it is posted below.

The rewrite rule must be in the Apache config, find it and port it to  
nginx.

HTH,  
— appa

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 10, 2010, 3:43am UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/7 "2010-10-10T03:43:48Z")

</div>

I tried your suggestion and it worked.

I have yet to learn more about “changing the location definition to  
include  
all and only the  
requests you want handled this way.”

Thanks

On 9 October 2010 11:12, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > (/home/rchurch/Data/Lazarus/CgiApps/spidersample.cgi)" while reading  
> > which is untrue. SCRIPT\_FILENAME is  
> > if they are already in the included /etc/nginx/fastcgi\_params. You can  
> > fastcgi\_param REQUEST\_METHOD $request\_method;

–  
Frank C.

=======================  
[http://devblog.brahmancreations.com](http://devblog.brahmancreations.com)

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 10, 2010, 3:43am UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/8 "2010-10-10T03:43:47Z")

</div>

On Fri, Oct 08, 2010 at 09:10:27PM +0100, Frank C. wrote:

> On 8 October 2010 16:55, Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > On Fri, Oct 08, 2010 at 04:02:48PM +0100, Frank C. wrote:

Hi there,

> > > With nginx instead of executing spidersample.cgi it treats  
> > > spidersample.cgi/hello as meaning a hello file in a spidersample.cgi  
> > > directory, and returns with a 404 error as there is no such directory.

> > > ```
> > > location ~ \.cgi$ {
> > > 
> > > ```

> > Your request for “/spidersample.cgi/hello” doesn’t match, and so doesn’t  
> > use this config.

> I removed the “$” and now this is the error message I get:
> 
> 2010/10/08 21:06:46 [error] 14628#0: \*22 FastCGI sent in stderr: “Cannot  
> chdir to script directory  
> (/home/rchurch/Data/Lazarus/CgiApps/spidersample.cgi)” while reading  
> response header from upstream, client: 127.0.0.1, server: localhost,  
> request: “GET /spidersample.cgi/hello HTTP/1.1”, upstream:  
> “fastcgi://unix:/tmp/rchurch\_cgi.sock:”, host: “localhost:8118”, referrer: "  
> [http://localhost:8118/spidersample.cgi](http://localhost:8118/spidersample.cgi)"

That suggests that this location block is now being used  
for this request, which is good. The error is because the  
fastcgi processor was told that the SCRIPT\_FILENAME was  
/home/rchurch/Data/Lazarus/CgiApps/spidersample.cgi/hello,  
which is untrue. SCRIPT\_FILENAME is  
“/home/rchurch/Data/Lazarus/CgiApps/spidersample.cgi”.

Also, the script itself almost certainly uses PATH\_INFO to determine  
which module of its own to use – “hello”, “echo”, or some other –  
so you’ll want to set that too.

The easiest way to do both is probably to use fastcgi\_split\_path\_info.  
See  
the two new lines below that include the string “path\_info”.

Note – it is possible that all of the fastcgi\_param lines are  
unnecessary  
if they are already in the included /etc/nginx/fastcgi\_params. You can  
experiment with removing them at leisure.

```
location ~ \.cgi {
        fastcgi_split_path_info (.*\.cgi)(/.*);
        include /etc/nginx/fastcgi_params;
        fastcgi_pass unix:/tmp/sysman_cgi.sock;
        fastcgi_param SCRIPT_FILENAME 

```

$document\_root$fastcgi\_script\_name;  
fastcgi\_param QUERY\_STRING $query\_string;  
fastcgi\_param REQUEST\_METHOD $request\_method;  
fastcgi\_param CONTENT\_TYPE $content\_type;  
fastcgi\_param CONTENT\_LENGTH $content\_length;  
fastcgi\_param PATH\_INFO $fastcgi\_path\_info;  
}

> > Then you can change the location definition to include all and only the  
> > requests you want handled this way.

That bit should still be done.

All the best,

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

---

<div class="post-metadata">

**Author:** ![vfcforums](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/v/85e7bf/32.png) [@vfcforums](https://www.ruby-forum.com/u/vfcforums)\
**Post date:** [October 11, 2010, 11:30pm UTC](https://www.ruby-forum.com/t/how-to-process-only-first-path-element-in-the-url-as-the-cgi-executable/196216/9 "2010-10-11T23:30:25Z")

</div>

On Sat, Oct 09, 2010 at 08:31:27PM +0100, Frank C. wrote:

Hi there,

> I tried your suggestion and it worked.

Good stuff.

> I have yet to learn more about “changing the location definition to include  
> all and only the  
> requests you want handled this way.”

It’s the usual security/convenience trade-off. If you know that you’re  
the only person who can add accessible urls to the server, then you  
can make sure that nothing with “.cgi” in the name that might lead to  
a security breach will be added.

I prefer to have a less generic configuration – so, for example, only  
files in the /cgi-bin/ namespace should be processed by the fastcgi  
server; or perhaps even only spidersample.cgi should be processed  
that way.

You have to decide what urls should go to the fastcgi service, and find  
one or more location patterns that match all of those urls, and match no  
other urls.

So maybe something like

location ~ spidersample.cgi

or

location ~^ /spidersample.cgi

or

location ~ /cgi-bin/\*.cgi

or even

location ~ /spidersample.cgi($|/)

will suit your requirements.

All the best,

## f

Francis D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)
