aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2026-06-25 09:01:50 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2026-06-25 09:01:50 +0000
commit7c5d186df1f7f00567660354905435cedffc3e20 (patch)
tree2911cf6d75a5be2a62fd493f2ad1a05ffc7c6bb3
parent51ff1577ce59449b36a86f21a90101bc2750943f (diff)
downloadtipidee-7c5d186df1f7f00567660354905435cedffc3e20.tar.gz
Implement fastcgi, except the protocol itselfHEADmain
-rw-r--r--doc/tipidee.conf.html24
-rw-r--r--package/deps.mak11
-rw-r--r--src/config/lexparse.c239
-rw-r--r--src/include/tipidee/conf.h10
-rw-r--r--src/include/tipidee/redirection.h38
-rw-r--r--src/include/tipidee/tipidee.h1
-rw-r--r--src/libtipidee/tipidee_conf_get_redirection.c42
-rw-r--r--src/tipideed/deps-exe/tipideed1
-rw-r--r--src/tipideed/fastcgi.c66
-rw-r--r--src/tipideed/redirection.c4
-rw-r--r--src/tipideed/rproxy.c11
-rw-r--r--src/tipideed/tipideed-internal.h5
-rw-r--r--src/tipideed/tipideed.c14
13 files changed, 312 insertions, 154 deletions
diff --git a/doc/tipidee.conf.html b/doc/tipidee.conf.html
index ead500f..da3126a 100644
--- a/doc/tipidee.conf.html
+++ b/doc/tipidee.conf.html
@@ -919,6 +919,28 @@ or IPv6. </li>
<em>resource</em> does not need to exist in the filesystem. The same caveats apply. </li>
</ul>
+<div id="fastcgi">
+<h4> <tt>fastcgi</tt> </h4>
+</div>
+
+<p>
+ <code> fastcgi <em>resource</em> unix <em>socketpath</em> </code> <br>
+ <code> fastcgi <em>resource</em> tcp <em>ip</em> <em>port</em> </code>
+</p>
+
+<ul>
+ <li> The <em>fastcgi</em> directive tells tipidee that when a client hits a
+given URL, the server should let a FastCGI application answer the request.
+For this exchange, tipideed will connect to the FastCGI server listening
+either to a Unix domain socket on <em>socketpath</em> or to an INET domain
+socket listening on IP address <em>ip</em> and port <em>port</em>. </li>
+ <li> It is similar to the <code>rproxy</code> directive, but whereas
+<code>rproxy</code> makes tipideed act as an HTTP client, <code>fastcgi</code>
+makes it act as a FastCGI client. </li>
+ <li> <em>resource</em> is the URI to redirect, relative to the current domain.
+ <li> Just like with the <code>redirect</code> and <code>rproxy</code> directives,
+<em>resource</em> does not need to exist in the filesystem. The same caveats apply. </li>
+</ul>
<div id="noredirect">
<h4> <tt>noredirect</tt> </h4>
@@ -934,7 +956,7 @@ useful to carve exceptions to a generic redirection policy: if you have a <code>
directive for directory A and a <code>noredirect</code> directive for resource B, and A is
a prefix of B, then B will not be redirected, but everything else under A will. </li>
<li> You can also use <code>noredirect</code> to prevent <em>resource</em> from being
-proxied by a more generic <code>rproxy</code> directive.
+proxied by a more generic <code>rproxy</code> or <code>fastcgi</code> directive.
</ul>
<div id="custom-response">
diff --git a/package/deps.mak b/package/deps.mak
index b5ad7e0..1d880dd 100644
--- a/package/deps.mak
+++ b/package/deps.mak
@@ -2,16 +2,16 @@
# This file has been generated by tools/gen-deps.sh
#
-src/include/tipidee/conf.h: src/include/tipidee/resattr.h src/include/tipidee/uri.h
+src/include/tipidee/conf.h: src/include/tipidee/redirection.h src/include/tipidee/resattr.h src/include/tipidee/uri.h
src/include/tipidee/log.h: src/include/tipidee/headers.h src/include/tipidee/resattr.h src/include/tipidee/rql.h
src/include/tipidee/response.h: src/include/tipidee/headers.h src/include/tipidee/rql.h
src/include/tipidee/rql.h: src/include/tipidee/method.h src/include/tipidee/uri.h
-src/include/tipidee/tipidee.h: src/include/tipidee/conf.h src/include/tipidee/config.h src/include/tipidee/headers.h src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/resattr.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/include/tipidee/util.h
+src/include/tipidee/tipidee.h: src/include/tipidee/conf.h src/include/tipidee/config.h src/include/tipidee/headers.h src/include/tipidee/log.h src/include/tipidee/method.h src/include/tipidee/redirection.h src/include/tipidee/resattr.h src/include/tipidee/response.h src/include/tipidee/rql.h src/include/tipidee/uri.h src/include/tipidee/util.h
src/tipideed/tipideed-internal.h: src/include/tipidee/tipidee.h
src/config/conftree.o src/config/conftree.lo: src/config/conftree.c src/config/tipidee-config-internal.h
src/config/defaults.o src/config/defaults.lo: src/config/defaults.c src/config/tipidee-config-internal.h src/include/tipidee/log.h
src/config/headers.o src/config/headers.lo: src/config/headers.c src/config/tipidee-config-internal.h src/include/tipidee/config.h
-src/config/lexparse.o src/config/lexparse.lo: src/config/lexparse.c src/config/tipidee-config-internal.h src/include/tipidee/config.h src/include/tipidee/log.h
+src/config/lexparse.o src/config/lexparse.lo: src/config/lexparse.c src/config/tipidee-config-internal.h src/include/tipidee/config.h src/include/tipidee/log.h src/include/tipidee/redirection.h src/include/tipidee/resattr.h
src/config/node.o src/config/node.lo: src/config/node.c src/config/tipidee-config-internal.h
src/config/repo.o src/config/repo.lo: src/config/repo.c src/config/tipidee-config-internal.h
src/config/tipidee-config-preprocess.o src/config/tipidee-config-preprocess.lo: src/config/tipidee-config-preprocess.c
@@ -21,7 +21,7 @@ src/libtipidee/tipidee_conf_get.o src/libtipidee/tipidee_conf_get.lo: src/libtip
src/libtipidee/tipidee_conf_get_argv.o src/libtipidee/tipidee_conf_get_argv.lo: src/libtipidee/tipidee_conf_get_argv.c src/include/tipidee/conf.h
src/libtipidee/tipidee_conf_get_content_type.o src/libtipidee/tipidee_conf_get_content_type.lo: src/libtipidee/tipidee_conf_get_content_type.c src/include/tipidee/conf.h
src/libtipidee/tipidee_conf_get_errorfile.o src/libtipidee/tipidee_conf_get_errorfile.lo: src/libtipidee/tipidee_conf_get_errorfile.c src/include/tipidee/conf.h
-src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_redirection.lo: src/libtipidee/tipidee_conf_get_redirection.c src/include/tipidee/conf.h
+src/libtipidee/tipidee_conf_get_redirection.o src/libtipidee/tipidee_conf_get_redirection.lo: src/libtipidee/tipidee_conf_get_redirection.c src/include/tipidee/conf.h src/include/tipidee/redirection.h
src/libtipidee/tipidee_conf_get_resattr.o src/libtipidee/tipidee_conf_get_resattr.lo: src/libtipidee/tipidee_conf_get_resattr.c src/include/tipidee/conf.h src/include/tipidee/resattr.h
src/libtipidee/tipidee_conf_get_resattr1.o src/libtipidee/tipidee_conf_get_resattr1.lo: src/libtipidee/tipidee_conf_get_resattr1.c src/include/tipidee/conf.h src/include/tipidee/resattr.h
src/libtipidee/tipidee_conf_get_responseheaders.o src/libtipidee/tipidee_conf_get_responseheaders.lo: src/libtipidee/tipidee_conf_get_responseheaders.c src/include/tipidee/conf.h
@@ -82,6 +82,7 @@ src/misc/ls.cgi.o src/misc/ls.cgi.lo: src/misc/ls.cgi.c src/include/tipidee/resp
src/misc/tipidee-logaggregate.o src/misc/tipidee-logaggregate.lo: src/misc/tipidee-logaggregate.c
src/tipideed/cgi.o src/tipideed/cgi.lo: src/tipideed/cgi.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h
src/tipideed/errors.o src/tipideed/errors.lo: src/tipideed/errors.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h
+src/tipideed/fastcgi.o src/tipideed/fastcgi.lo: src/tipideed/fastcgi.c src/include/tipidee/tipidee.h src/tipideed/tipideed-internal.h
src/tipideed/harden.o src/tipideed/harden.lo: src/tipideed/harden.c src/tipideed/tipideed-internal.h
src/tipideed/options.o src/tipideed/options.lo: src/tipideed/options.c src/include/tipidee/log.h src/include/tipidee/response.h src/tipideed/tipideed-internal.h
src/tipideed/redirection.o src/tipideed/redirection.lo: src/tipideed/redirection.c src/include/tipidee/log.h src/include/tipidee/response.h src/include/tipidee/util.h src/tipideed/tipideed-internal.h
@@ -114,5 +115,5 @@ ls.cgi: src/misc/ls.cgi.o libtipidee.a.xyzzy -lskarnet
tipidee-logaggregate: EXTRA_LIBS :=
tipidee-logaggregate: src/misc/tipidee-logaggregate.o -lskarnet
tipideed: EXTRA_LIBS := ${SOCKET_LIB} ${SYSCLOCK_LIB} ${SPAWN_LIB}
-tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/errors.o src/tipideed/harden.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/redirection.o src/tipideed/rproxy.o src/tipideed/send_file.o src/tipideed/stream.o src/tipideed/trace.o src/tipideed/util.o libtipidee.a.xyzzy -lskarnet
+tipideed: src/tipideed/tipideed.o src/tipideed/cgi.o src/tipideed/errors.o src/tipideed/harden.o src/tipideed/fastcgi.o src/tipideed/options.o src/tipideed/regular.o src/tipideed/redirection.o src/tipideed/rproxy.o src/tipideed/send_file.o src/tipideed/stream.o src/tipideed/trace.o src/tipideed/util.o libtipidee.a.xyzzy -lskarnet
INTERNAL_LIBS :=
diff --git a/src/config/lexparse.c b/src/config/lexparse.c
index b9136ad..dd74e65 100644
--- a/src/config/lexparse.c
+++ b/src/config/lexparse.c
@@ -5,6 +5,7 @@
#include <stdlib.h>
#include <errno.h>
+#include <skalibs/uint16.h>
#include <skalibs/uint32.h>
#include <skalibs/fmtscan.h>
#include <skalibs/buffer.h>
@@ -14,10 +15,12 @@
#include <skalibs/skamisc.h>
#include <tipidee/log.h>
+#include <tipidee/redirection.h>
+#include <tipidee/resattr.h>
#include <tipidee/config.h>
#include "tipidee-config-internal.h"
-#define dietoobig() strerr_diefu1sys(100, "read configuration")
+#define dietoobig() strerr_diefusys(100, "read configuration")
typedef struct mdt_s mdt, *mdt_ref ;
struct mdt_s
@@ -47,6 +50,7 @@ enum directivevalue_e
T_REDIRECT,
T_NOREDIRECT,
T_RPROXY,
+ T_FASTCGI,
T_CGI,
T_NONCGI,
T_NPH,
@@ -69,6 +73,13 @@ enum customheaderoptionvalue_e
CHO_NEVER
} ;
+static unsigned int log2u (uint32_t x)
+{
+ unsigned int n = 0 ;
+ while (x >>= 1) n++ ;
+ return n ;
+}
+
static void conftree_checkunique (char const *key, mdt const *md)
{
node const *node = conftree_search(key) ;
@@ -76,7 +87,7 @@ static void conftree_checkunique (char const *key, mdt const *md)
{
char fmt[UINT32_FMT] ;
fmt[uint32_fmt(fmt, node->line)] = 0 ;
- strerr_diefn(1, 12, "duplicate ", "key ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ;
+ strerr_dief(1, "duplicate ", "key ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ;
}
}
@@ -87,7 +98,7 @@ static void headers_checkunique (char const *key, mdt const *md)
{
char fmt[UINT32_FMT] ;
fmt[uint32_fmt(fmt, node->line)] = 0 ;
- strerr_diefn(1, 12, "duplicate ", "header ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ;
+ strerr_dief(1, "duplicate ", "header ", key, " in file ", g.storage.s + md->filepos, " line ", md->linefmt, ", previously defined", " in file ", g.storage.s + node->filepos, " line ", fmt) ;
}
}
@@ -116,11 +127,11 @@ static inline void parse_global (char const *s, size_t const *word, size_t n, md
uint32_t u ;
char pack[4] ;
if (n != 2)
- strerr_dief8x(1, "too ", n < 2 ? "few" : "many", " arguments to directive ", "global", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", n < 2 ? "few" : "many", " arguments to directive ", "global", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
x = BSEARCH(char const *, s + word[0], globalkeys) ;
if (!x) strerr_dief6x(1, "unrecognized global setting ", s + word[0], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!uint320_scan(s + word[1], &u))
- strerr_dief6x(1, "invalid (non-numeric) value for global setting ", s + word[0], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "invalid (non-numeric) value for global setting ", s + word[0], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
uint32_pack_big(pack, u) ;
{
size_t len = strlen(*x) ;
@@ -135,7 +146,7 @@ static inline void parse_indexfile (char const *s, size_t const *word, size_t n,
{
node node ;
if (!n)
- strerr_dief8x(1, "too ", "few", " arguments to directive ", "index_file", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", "few", " arguments to directive ", "index_file", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
conftree_checkunique("G:index-file", md) ;
confnode_start(&node, "G:index-file", md->filepos, md->line) ;
for (size_t i = 0 ; i < n ; i++)
@@ -164,14 +175,14 @@ static inline void parse_log (char const *s, size_t const *word, size_t n, mdt c
uint32_t v = 0 ;
char pack[4] ;
if (!n)
- strerr_dief8x(1, "too ", "few", " arguments to directive ", "log", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", "few", " arguments to directive ", "log", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
for (size_t i = 0 ; i < n ; i++)
{
struct namevalue_s const *l = BSEARCH(struct namevalue_s, s + word[i], logkeys) ;
if (!l) strerr_dief6x(1, "unrecognized log setting ", s + word[i], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (l->value) v |= l->value ;
else if (n == 1) v = 0 ;
- else strerr_dief5x(1, "log nothing cannot be mixed with other log values", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ else strerr_dief(1, "log nothing cannot be mixed with other log values", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
}
uint32_pack_big(pack, v) ;
@@ -182,17 +193,17 @@ static inline void parse_contenttype (char const *s, size_t const *word, size_t
{
char const *ct ;
if (n < 2)
- strerr_dief8x(1, "too ", "few", " arguments to directive ", "content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", "few", " arguments to directive ", "content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
ct = s + *word++ ;
if (!strchr(ct, '/'))
- strerr_dief6x(1, "Content-Type must include a slash", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "Content-Type must include a slash", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
n-- ;
for (size_t i = 0 ; i < n ; i++)
{
if (s[word[i]] == '\"' && s[word[i]+1] == '\"' && !s[word[i]+2])
add_unique("T:", ct, strlen(ct) + 1, md) ;
else if (s[word[i]] != '.')
- strerr_dief6x(1, "file extensions must be \"\" or start with a dot", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "file extensions must be \"\" or start with a dot", " - check directive content-type", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
else
{
size_t len = strlen(s + word[i]) ;
@@ -217,11 +228,11 @@ static inline void parse_customheader (char const *s, size_t const *word, size_t
} ;
struct namevalue_s const *p ;
if (n < 2)
- strerr_dief8x(1, "too ", "few", " arguments to directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", "few", " arguments to directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
p = BSEARCH(struct namevalue_s, s + *word, choptions) ;
- if (!p) strerr_dief9x(1, "invalid subcommand ", s + *word, " for", " directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (!p) strerr_dief(1, "invalid subcommand ", s + *word, " for", " directive ", "custom-header", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if ((p->value == CHO_ADD || p->value == CHO_ALWAYS) == (n == 2))
- strerr_dief10x(1, "too ", n == 2 ? "few" : "many", " arguments to directive ", "custom-header", " ", p->name, " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", n == 2 ? "few" : "many", " arguments to directive ", "custom-header", " ", p->name, " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
word++ ; n-- ;
{
size_t len = strlen(s + *word) ;
@@ -229,7 +240,7 @@ static inline void parse_customheader (char const *s, size_t const *word, size_t
memcpy(key, s + *word++, len + 1) ; n-- ;
header_canonicalize(key) ;
if (!header_allowed(key))
- strerr_dief7x(1, "header ", key, " cannot be customized", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "header ", key, " cannot be customized", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
headers_checkunique(key, md) ;
switch (p->value)
{
@@ -253,11 +264,11 @@ static inline void parse_customheader (char const *s, size_t const *word, size_t
static inline void parse_noredirect (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md)
{
if (n != 1)
- strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", "noredirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", "noredirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!domain)
- strerr_dief6x(1, "noredirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "noredirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[*word] != '/')
- strerr_dief6x(1, "noredirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "noredirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
{
size_t urlen = strlen(s + *word) ;
char key[3 + domainlen + urlen] ;
@@ -266,8 +277,38 @@ static inline void parse_noredirect (char const *s, size_t const *word, size_t n
memcpy(key + 2, domain, domainlen) ;
memcpy(key + 2 + domainlen, s + *word, urlen) ;
key[2 + domainlen + urlen] = 0 ;
- add_unique(key, "\200", 2, md) ;
+ add_unique(key, "", 1, md) ;
+ }
+}
+
+static void make_redirect_node (char const *sub, uint8_t type, uint8_t flags, char const *addr, uint16_t port, char const *domain, size_t domainlen, mdt const *md)
+{
+ node node ;
+ size_t sublen = strlen(sub) ;
+ char key[3 + domainlen + sublen] ;
+ if (sub[sublen - 1] == '/') { key[0] = 'r' ; sublen-- ; } else key[0] = 'R' ;
+ key[1] = ':' ;
+ memcpy(key + 2, domain, domainlen) ;
+ memcpy(key + 2 + domainlen, sub, sublen) ;
+ key[2 + domainlen + sublen] = 0 ;
+ conftree_checkunique(key, md) ;
+ confnode_start(&node, key, md->filepos, md->line) ;
+ confnode_add(&node, (char *)&type, 1) ;
+ confnode_add(&node, (char *)&flags, 1) ;
+ if (type >= 2 && flags & 1)
+ {
+ char pack[2] ;
+ uint16_pack_big(pack, port) ;
+ confnode_add(&node, pack, 2) ;
+ confnode_add(&node, addr, flags & 2 ? 16 : 4) ;
+ }
+ else
+ {
+ size_t addrlen = strlen(addr) ;
+ confnode_add(&node, addr, addrlen - (addr[addrlen - 1] == '/')) ;
+ confnode_add(&node, "", 1) ;
}
+ conftree_add(&node) ;
}
static inline void parse_redirect (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md)
@@ -276,104 +317,65 @@ static inline void parse_redirect (char const *s, size_t const *word, size_t n,
uint32_t code ;
uint32_t i = 0 ;
if (n != 3)
- strerr_dief8x(1, "too ", n > 3 ? "many" : "few", " arguments to directive ", "redirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", n > 3 ? "many" : "few", " arguments to directive ", "redirect", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!domain)
- strerr_dief6x(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[word[0]] != '/')
- strerr_dief6x(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!uint320_scan(s + word[1], &code))
- strerr_dief6x(1, "invalid redirection code ", s + word[1], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "invalid redirection code ", s + word[1], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
for (; i < 4 ; i++) if (code == codes[i]) break ;
if (i >= 4)
- strerr_dief6x(1, "redirection code ", "must be 301, 302, 307 or 308", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "redirection code ", "must be 301, 302, 307 or 308", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (strncmp(s + word[2], "http://", 7) && strncmp(s + word[2], "https://", 8))
- strerr_dief5x(1, "redirection target must be a full http:// or https:// target", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
- {
- node node ;
- size_t urlen = strlen(s + word[0]) ;
- char key[3 + domainlen + urlen] ;
- if (s[word[0] + urlen - 1] == '/') { key[0] = 'r' ; urlen-- ; } else key[0] = 'R' ;
- key[1] = ':' ;
- memcpy(key + 2, domain, domainlen) ;
- memcpy(key + 2 + domainlen, s + word[0], urlen) ;
- key[2 + domainlen + urlen] = 0 ;
- conftree_checkunique(key, md) ;
- confnode_start(&node, key, md->filepos, md->line) ;
- key[0] = '@' | i ;
- confnode_add(&node, &key[0], 1) ;
- urlen = strlen(s + word[2]) ;
- confnode_add(&node, s + word[2], urlen - (s[word[2] + urlen - 1] == '/')) ;
- confnode_add(&node, "", 1) ;
- conftree_add(&node) ;
- }
+ strerr_dief(1, "redirection target must be a full http:// or https:// target", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ make_redirect_node(s + word[0], TIPIDEE_REDIR_REDIRECT, i, s + word[2], 0, domain, domainlen, md) ;
}
-static inline void parse_rproxy (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md)
+static inline void parse_rproxy_fastcgi (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, int isfcgi)
{
- uint8_t type ;
+ char ip[16] ;
+ uint16_t port = 0 ;
+ uint8_t flags ;
if (n < 3 || n > 4)
- strerr_dief8x(1, "too ", n > 4 ? "many" : "few", " arguments to directive ", "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", n > 4 ? "many" : "few", " arguments to directive ", isfcgi ? "fastcgi" : "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!domain)
- strerr_dief6x(1, "rproxy redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "redirection", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[word[0]] != '/')
- strerr_dief6x(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
- if (!strcmp(s + word[1], "unix"))
- type = 48 ;
- else if (!strcmp(s + word[1], "tcp"))
- type = 32 ;
+ strerr_dief(1, "redirected resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (!strcmp(s + word[1], "unix")) flags = 0 ;
+ else if (!strcmp(s + word[1], "tcp")) flags = 1 ;
else
- strerr_dief7x(1, "rproxy", " directive", " needs to specify unix or tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, isfcgi ? "fastcgi" : "rproxy", " directive", " needs to specify unix or tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (flags & 1)
{
- node node ;
- size_t urlen = strlen(s + word[0]) ;
- char key[3 + domainlen + urlen] ;
- if (s[word[0] + urlen - 1] == '/') { key[0] = 'r' ; urlen-- ; } else key[0] = 'R' ;
- key[1] = ':' ;
- memcpy(key + 2, domain, domainlen) ;
- memcpy(key + 2 + domainlen, s + word[0], urlen) ;
- key[2 + domainlen + urlen] = 0 ;
- conftree_checkunique(key, md) ;
- confnode_start(&node, key, md->filepos, md->line) ;
-
- if (type == 48)
- {
- if (n != 3)
- strerr_dief8x(1, "too ", "many" , " arguments to directive ", "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
- key[0] = '@' | type ;
- confnode_add(&node, &key[0], 1) ;
- confnode_add(&node, s + word[2], strlen(s + word[2]) + 1) ;
- }
- else
- {
- char ip[16] ;
- uint16_t port ;
- if (n != 4)
- strerr_dief8x(1, "too ", "few" , " arguments to directive ", "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
- if (ip6_scan(s + word[2], ip)) type |= 8 ;
- else if (!ip4_scan(s + word[2], ip))
- strerr_dief8x(1, "invalid ip address ", "in directive ", "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
- if (!uint160_scan(s + word[3], &port))
- strerr_dief8x(1, "invalid port ", "in directive ", "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
- key[0] = '@' | type ;
- uint16_pack_big(key+1, port) ;
- confnode_add(&node, key, 3) ;
- confnode_add(&node, ip, type & 8 ? 16 : 4) ;
- }
- confnode_add(&node, "", 1) ;
- conftree_add(&node) ;
+ if (n != 4)
+ strerr_dief(1, "too ", "few" , " arguments to directive ", isfcgi ? "fastcgi" : "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (ip6_scan(s + word[2], ip)) flags |= 2 ;
+ else if (!ip4_scan(s + word[2], ip))
+ strerr_dief(1, "invalid ip address ", "in directive ", isfcgi ? "fastcgi" : "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ if (!uint160_scan(s + word[3], &port))
+ strerr_dief(1, "invalid port ", "in directive ", isfcgi ? "fastcgi" : "rproxy", " tcp", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ }
+ else
+ {
+ if (n != 3)
+ strerr_dief(1, "too ", "many" , " arguments to directive ", isfcgi ? "fastcgi" : "rproxy", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
}
+ make_redirect_node(s + word[0], 2 + isfcgi, flags, flags & 1 ? ip : s + word[2], port, domain, domainlen, md) ;
}
-static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, uint8_t bit, int h)
+static void parse_bitattr (char const *s, size_t const *word, size_t n, char const *domain, size_t domainlen, mdt const *md, uint32_t flag, int h)
{
static char const *const attr[5][2] = { { "noncgi", "cgi" }, { "nonnph", "nph" }, { "noauth", "basic-auth" }, { "noautochunk", "autochunk" }, { "norealtime", "realtime" } } ;
+ unsigned int bit = log2u(flag) ;
if (n != 1)
- strerr_dief8x(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][h], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "too ", n > 1 ? "many" : "few", " arguments to directive ", attr[bit][h], " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (!domain)
- strerr_dief7x(1, "resource attribute ", "definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "resource attribute ", "definition", " without a domain directive", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
if (s[*word] != '/')
- strerr_dief6x(1, "resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
+ strerr_dief(1, "resource", " must start with /", " in file ", g.storage.s + md->filepos, " line ", md->linefmt) ;
{
node const *oldnode ;
size_t arglen = strlen(s + *word) ;
@@ -389,22 +391,22 @@ static void parse_bitattr (char const *s, size_t const *word, size_t n, char con
uint32_t flags, mask ;
uint32_unpack_big(g.storage.s + oldnode->data, &flags) ;
uint32_unpack_big(g.storage.s + oldnode->data + 4, &mask) ;
- if (mask & 1 << bit)
+ if (mask & flag)
{
char fmt[UINT32_FMT] ;
fmt[uint32_fmt(fmt, oldnode->line)] = 0 ;
- strerr_diefn(1, 13, "resource attribute ", attr[bit][h], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
+ strerr_dief(1, "resource attribute ", attr[bit][h], " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
}
- mask |= 1 << bit ;
- if (h) flags |= 1 << bit ; else flags &= ~(1 << bit) ;
+ mask |= flag ;
+ if (h) flags |= flag ; else flags &= ~flag ;
uint32_pack_big(g.storage.s + oldnode->data, flags) ;
uint32_pack_big(g.storage.s + oldnode->data + 4, mask) ;
}
else
{
node node ;
- uint32_t flags = h ? 1 << bit : 0 ;
- uint32_t mask = 1 << bit ;
+ uint32_t flags = h ? flag : 0 ;
+ uint32_t mask = flag ;
char val[9] = "\0\0\0\0\0\0\0\0" ;
uint32_pack_big(val, flags) ;
uint32_pack_big(val + 4, mask) ;
@@ -435,11 +437,20 @@ static inline void parse_filetype (char const *s, size_t const *word, size_t n,
oldnode = conftree_search(key) ;
if (oldnode)
{
+ uint32_t oldflags ;
+ uint32_unpack_big(g.storage.s + oldnode->data, &oldflags) ;
+ if (oldflags & (TIPIDEE_RA_FLAG_CGI | TIPIDEE_RA_FLAG_NPH))
+ {
+ char fmt[UINT32_FMT] ;
+ fmt[uint32_fmt(fmt, oldnode->line)] = 0 ;
+ strerr_dief(1, "incompatible", "file-type", " definition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; conflicting attribute", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
+ }
+
if (g.storage.s[oldnode->data + 8])
{
char fmt[UINT32_FMT] ;
fmt[uint32_fmt(fmt, oldnode->line)] = 0 ;
- strerr_diefn(1, 12, "file-type", " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
+ strerr_dief(1, "file-type", " redefinition", " in file ", g.storage.s + md->filepos, " line ", md->linefmt, "; previous definition", " in file ", g.storage.s + oldnode->filepos, " line ", fmt, " or later") ;
}
else
{
@@ -499,6 +510,7 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st
{ .name = "custom-header", .value = T_CUSTOMHEADER },
{ .name = "custom-response", .value = T_CUSTOMRESPONSE },
{ .name = "domain", .value = T_DOMAIN },
+ { .name = "fastcgi", .value = T_FASTCGI },
{ .name = "file-type", .value = T_FILETYPE },
{ .name = "global", .value = T_GLOBAL },
{ .name = "index-file", .value = T_INDEXFILE },
@@ -579,42 +591,45 @@ static inline void process_line (char const *s, size_t const *word, size_t n, st
parse_redirect(s, word, n, domain->s, domain->len, md) ;
break ;
case T_RPROXY :
- parse_rproxy(s, word, n, domain->s, domain->len, md) ;
+ parse_rproxy_fastcgi(s, word, n, domain->s, domain->len, md, 0) ;
+ break ;
+ case T_FASTCGI :
+ parse_rproxy_fastcgi(s, word, n, domain->s, domain->len, md, 1) ;
break ;
case T_NOREDIRECT :
parse_noredirect(s, word, n, domain->s, domain->len, md) ;
break ;
case T_CGI :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 0, 1) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_CGI, 1) ;
break ;
case T_NONCGI :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 0, 0) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_CGI, 0) ;
break ;
case T_NPH :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 1, 1) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_NPH, 1) ;
break ;
case T_NONNPH :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 1, 0) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_NPH, 0) ;
break ;
case T_BASICAUTH :
strerr_warnw5x("file ", g.storage.s + md->filepos, " line ", md->linefmt, ": directive basic-auth not implemented in tipidee-" TIPIDEE_VERSION) ;
- parse_bitattr(s, word, n, domain->s, domain->len, md, 2, 1) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_BA, 1) ;
break ;
case T_NOAUTH :
strerr_warnw5x("file ", g.storage.s + md->filepos, " line ", md->linefmt, ": directive basic-auth not implemented in tipidee-" TIPIDEE_VERSION) ;
- parse_bitattr(s, word, n, domain->s, domain->len, md, 2, 0) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_BA, 0) ;
break ;
case T_AUTOCHUNK :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 3, 1) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_AUTOCHUNK, 1) ;
break ;
case T_NOAUTOCHUNK :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 3, 0) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_AUTOCHUNK, 0) ;
break ;
case T_REALTIME :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 4, 1) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_REALTIME, 1) ;
break ;
case T_NOREALTIME :
- parse_bitattr(s, word, n, domain->s, domain->len, md, 4, 0) ;
+ parse_bitattr(s, word, n, domain->s, domain->len, md, TIPIDEE_RA_FLAG_REALTIME, 0) ;
break ;
case T_FILETYPE :
parse_filetype(s, word, n, domain->s, domain->len, md) ;
diff --git a/src/include/tipidee/conf.h b/src/include/tipidee/conf.h
index a173d6a..95273d6 100644
--- a/src/include/tipidee/conf.h
+++ b/src/include/tipidee/conf.h
@@ -10,6 +10,7 @@
#include <skalibs/uint32.h>
#include <skalibs/cdb.h>
+#include <tipidee/redirection.h>
#include <tipidee/resattr.h>
#include <tipidee/uri.h>
@@ -22,15 +23,6 @@ struct tipidee_conf_s
} ;
#define TIPIDEE_CONF_ZERO { .c = CDB_ZERO }
-typedef struct tipidee_redirection_s tipidee_redirection, *tipidee_redirection_ref ;
-struct tipidee_redirection_s
-{
- char const *sub ;
- char const *location ;
- uint8_t type ;
-} ;
-#define TIPIDEE_REDIRECTION_ZERO { .sub = 0, .location = 0, .type = 0 }
-
extern void tipidee_conf_free (tipidee_conf *) ;
extern int tipidee_conf_init (tipidee_conf *, char const *) ;
diff --git a/src/include/tipidee/redirection.h b/src/include/tipidee/redirection.h
new file mode 100644
index 0000000..6c8d7d1
--- /dev/null
+++ b/src/include/tipidee/redirection.h
@@ -0,0 +1,38 @@
+/* ISC license. */
+
+#ifndef TIPIDEE_REDIRECTION_H
+#define TIPIDEE_REDIRECTION_H
+
+#include <stdint.h>
+
+enum tipidee_redir_type_e
+{
+ TIPIDEE_REDIR_NONE,
+ TIPIDEE_REDIR_REDIRECT,
+ TIPIDEE_REDIR_RPROXY,
+ TIPIDEE_REDIR_FASTCGI
+} ;
+
+
+ /* for redirect */
+#define TIPIDEE_REDIR_307 0x0
+#define TIPIDEE_REDIR_308 0x1
+#define TIPIDEE_REDIR_302 0x2
+#define TIPIDEE_REDIR_301 0x3
+
+ /* for rproxy or fastcgi */
+#define TIPIDEE_REDIR_ISINET 0x1
+#define TIPIDEE_REDIR_ISV6 0x2
+
+typedef struct tipidee_redirection_s tipidee_redirection, *tipidee_redirection_ref ;
+struct tipidee_redirection_s
+{
+ char const *sub ;
+ char const *addr ;
+ uint16_t port ;
+ uint8_t type : 4 ;
+ uint8_t flags : 4 ;
+} ;
+#define TIPIDEE_REDIRECTION_ZERO { .sub = 0, .addr = 0, .port = 0, .type = TIPIDEE_REDIR_NONE, .flags = 0 }
+
+#endif
diff --git a/src/include/tipidee/tipidee.h b/src/include/tipidee/tipidee.h
index 7c5154c..50ee7bf 100644
--- a/src/include/tipidee/tipidee.h
+++ b/src/include/tipidee/tipidee.h
@@ -8,6 +8,7 @@
#include <tipidee/headers.h>
#include <tipidee/log.h>
#include <tipidee/method.h>
+#include <tipidee/redirection.h>
#include <tipidee/resattr.h>
#include <tipidee/response.h>
#include <tipidee/rql.h>
diff --git a/src/libtipidee/tipidee_conf_get_redirection.c b/src/libtipidee/tipidee_conf_get_redirection.c
index a8397ec..9c2456a 100644
--- a/src/libtipidee/tipidee_conf_get_redirection.c
+++ b/src/libtipidee/tipidee_conf_get_redirection.c
@@ -1,35 +1,53 @@
/* ISC license. */
#include <errno.h>
+#include <stdint.h>
#include <string.h>
+#include <skalibs/uint16.h>
+#include <skalibs/cdb.h>
+
+#include <tipidee/redirection.h>
#include <tipidee/conf.h>
#include <skalibs/posixishard.h>
-static int get_redir (tipidee_conf const *conf, size_t minl, char *key, size_t l, char const *path, tipidee_redirection *r)
+static int get_redir (tipidee_conf const *conf, size_t minl, char *key, size_t l, char const *path, tipidee_redirection *rd)
{
- char const *v = 0 ;
+ cdb_data data ;
+ int r = 0 ;
key[0] = 'R' ;
key[l] = '/' ;
errno = ENOENT ;
- while (!v)
+ while (!r)
{
if (errno != ENOENT) return -1 ;
while (l >= minl && key[l] != '/') l-- ;
- if (l < minl) break ;
+ if (l < minl) return 0 ;
key[l--] = 0 ;
- v = tipidee_conf_get_string(conf, key) ;
+ r = tipidee_conf_get(conf, key, &data) ;
key[0] = 'r' ;
}
- if (!v || ((unsigned char)v[0] & 128)) return 0 ;
- r->type = v[0] ;
- r->location = v+1 ;
- r->sub = path + (l - minl + 1) ;
+ if (data.len < 5) return (errno = EILSEQ, -1) ;
+ rd->sub = path + (l - minl + 1) ;
+ rd->type = *data.s++ ; data.len-- ;
+ if (!rd->type)
+ return data.len ? (errno = EILSEQ, -1) : 1 ;
+ rd->flags = *data.s++ ; data.len-- ;
+ if (rd->type >= 2 && rd->flags & TIPIDEE_REDIR_ISINET)
+ {
+ if (data.len != (rd->flags & TIPIDEE_REDIR_ISV6 ? 18 : 6))
+ return (errno = EILSEQ, -1) ;
+ uint16_unpack_big(data.s, &rd->port) ;
+ data.s += 2 ; data.len -= 2 ;
+ }
+ else if (data.s[data.len - 1])
+ return (errno = EILSEQ, -1) ;
+ rd->addr = data.s ;
return 1 ;
}
-int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot, size_t docrootlen, char const *path, tipidee_redirection *r)
+int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot, size_t docrootlen, char const *path, tipidee_redirection *rd)
{
size_t pathlen = strlen(path) ;
char key[docrootlen + pathlen + 3] ;
@@ -37,7 +55,7 @@ int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot,
memcpy(key + 2, docroot, docrootlen) ;
memcpy(key + 2 + docrootlen, path, pathlen + 1) ;
{
- int e = get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, r) ;
+ int e = get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, rd) ;
if (e) return e ;
}
{
@@ -47,5 +65,5 @@ int tipidee_conf_get_redirection (tipidee_conf const *conf, char const *docroot,
}
memcpy(key + 2, docroot, docrootlen) ;
memcpy(key + 2 + docrootlen, path, pathlen + 1) ;
- return get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, r) ;
+ return get_redir(conf, 2 + docrootlen, key, 2 + docrootlen + pathlen, path, rd) ;
}
diff --git a/src/tipideed/deps-exe/tipideed b/src/tipideed/deps-exe/tipideed
index c099ab9..bc32b06 100644
--- a/src/tipideed/deps-exe/tipideed
+++ b/src/tipideed/deps-exe/tipideed
@@ -1,6 +1,7 @@
cgi.o
errors.o
harden.o
+fastcgi.o
options.o
regular.o
redirection.o
diff --git a/src/tipideed/fastcgi.c b/src/tipideed/fastcgi.c
new file mode 100644
index 0000000..5d5debf
--- /dev/null
+++ b/src/tipideed/fastcgi.c
@@ -0,0 +1,66 @@
+/* ISC license. */
+
+#include <stdint.h>
+#include <unistd.h>
+#include <strings.h>
+
+#include <skalibs/uint16.h>
+#include <skalibs/fmtscan.h>
+#include <skalibs/tai.h>
+#include <skalibs/buffer.h>
+#include <skalibs/djbunix.h>
+#include <skalibs/socket.h>
+#include <skalibs/ip46.h>
+#include <skalibs/unix-timed.h>
+
+#include <tipidee/tipidee.h>
+#include "tipideed-internal.h"
+
+#define putit(b, s, deadline) if (buffer_timed_puts_g(b, s, deadline) == -1) die500sys(rql, 111, docroot, "write to ", fn)
+
+static void do_fastcgi (tipidee_rql const *rql, int fd, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen, tain const *deadline, char const *fn)
+{
+ char buf[4096] ;
+ buffer b = BUFFER_INIT(&buffer_write, fd, buf, 4096) ;
+ _exit(0) ;
+}
+
+static void fastcgi_unix (tipidee_rql const *rql, char const *socketpath, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen)
+{
+ tain deadline ;
+ int fd = ipc_stream_nbcoe() ;
+ if (fd == -1) die500sys(rql, 111, docroot, "create socket") ;
+ tain_add_g(&deadline, &g.readtto) ;
+ if (!ipc_timed_connect_g(fd, socketpath, &deadline)) die500sys(rql, 111, docroot, "connect to ", socketpath) ;
+ do_fastcgi(rql, fd, sub, docroot, hdr, body, bodylen, &deadline, socketpath) ;
+ fd_close(fd) ;
+}
+
+static inline void fastcgi_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, int is6, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen)
+{
+ tain deadline ;
+ size_t m = 0 ;
+ int fd = socket_tcp46_nbcoe(is6) ;
+ char fmt[IP6_FMT + UINT16_FMT + 2] ;
+ if (fd == -1) die500sys(rql, 111, docroot, "create socket") ;
+ tain_add_g(&deadline, &g.readtto) ;
+ if (is6) fmt[m++] = '[' ;
+ m += is6 ? ip6_fmt(fmt + m, ip) : ip4_fmt(fmt + m, ip) ;
+ if (is6) fmt[m++] = ']' ;
+ fmt[m++] = ':' ;
+ m += uint16_fmt(fmt + m, port) ;
+ fmt[m++] = 0 ;
+
+ if (!(is6 ? socket_deadlineconnstamp6_g(fd, ip, port, &deadline) : socket_deadlineconnstamp4_g(fd, ip, port, &deadline)))
+ die500sys(rql, 111, docroot, "connect to ", fmt) ;
+ do_fastcgi(rql, fd, sub, docroot, hdr, body, bodylen, &deadline, fmt) ;
+ fd_close(fd) ;
+}
+
+void fastcgi (tipidee_rql const *rql, tipidee_redirection const *rd, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen)
+{
+ if (rd->flags & TIPIDEE_REDIR_ISINET)
+ fastcgi_tcp(rql, rd->addr, rd->port, !!(rd->flags & TIPIDEE_REDIR_ISV6), rd->sub, docroot, hdr, body, bodylen) ;
+ else
+ fastcgi_unix(rql, rd->addr, rd->sub, docroot, hdr, body, bodylen) ;
+}
diff --git a/src/tipideed/redirection.c b/src/tipideed/redirection.c
index ce32e44..f13eabb 100644
--- a/src/tipideed/redirection.c
+++ b/src/tipideed/redirection.c
@@ -15,12 +15,12 @@ void respond_30x (tipidee_rql const *rql, tipidee_redirection const *rd)
static unsigned int const status[4] = { 307, 308, 302, 301 } ;
tipidee_defaulttext dt ;
tain deadline ;
- unsigned int type = rd->type & 3 ;
+ unsigned int type = rd->flags & 3 ;
tipidee_util_defaulttext(status[type], &dt) ;
tipidee_response_status(buffer_1, rql, status[type], dt.reason) ;
tipidee_response_header_writeall_G(buffer_1, g.rhdr, g.rhdrn, 0) ;
buffer_putsnoflush(buffer_1, "Content-Length: 0\r\nLocation: ") ;
- buffer_putsnoflush(buffer_1, rd->location) ;
+ buffer_putsnoflush(buffer_1, rd->addr) ;
if (rd->sub) buffer_putsnoflush(buffer_1, rd->sub) ;
buffer_putnoflush(buffer_1, "\r\n\r\n", 4) ;
tipidee_log_answer(g.logv, rql, status[type], 0) ;
diff --git a/src/tipideed/rproxy.c b/src/tipideed/rproxy.c
index 5b0ec29..10e9692 100644
--- a/src/tipideed/rproxy.c
+++ b/src/tipideed/rproxy.c
@@ -64,7 +64,7 @@ static void rproxy_unix (tipidee_rql const *rql, char const *socketpath, char co
fd_close(fd) ;
}
-static void rproxy_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, int is6, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen)
+static inline void rproxy_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, int is6, char const *sub, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen)
{
tain deadline ;
size_t m = 0 ;
@@ -87,11 +87,8 @@ static void rproxy_tcp (tipidee_rql const *rql, char const *ip, uint16_t port, i
void rproxy (tipidee_rql const *rql, tipidee_redirection const *rd, char const *docroot, tipidee_headers const *hdr, char const *body, size_t bodylen)
{
- if (rd->type & 16) rproxy_unix(rql, rd->location, rd->sub, docroot, hdr, body, bodylen) ;
+ if (rd->flags & TIPIDEE_REDIR_ISINET)
+ rproxy_tcp(rql, rd->addr, rd->port, !!(rd->flags & TIPIDEE_REDIR_ISV6), rd->sub, docroot, hdr, body, bodylen) ;
else
- {
- uint16_t port ;
- uint16_unpack_big(rd->location, &port) ;
- rproxy_tcp(rql, rd->location + 2, port, !!(rd->type & 8), rd->sub, docroot, hdr, body, bodylen) ;
- }
+ rproxy_unix(rql, rd->addr, rd->sub, docroot, hdr, body, bodylen) ;
}
diff --git a/src/tipideed/tipideed-internal.h b/src/tipideed/tipideed-internal.h
index e3e014c..2cc8186 100644
--- a/src/tipideed/tipideed-internal.h
+++ b/src/tipideed/tipideed-internal.h
@@ -129,6 +129,11 @@ extern void respond_30x (tipidee_rql const *, tipidee_redirection const *) ;
extern void rproxy (tipidee_rql const *, tipidee_redirection const *, char const *, tipidee_headers const *, char const *, size_t) ;
+ /* fastcgi */
+
+extern void fastcgi (tipidee_rql const *, tipidee_redirection const *, char const *, tipidee_headers const *, char const *, size_t) ;
+
+
/* trace */
extern int respond_trace (tipidee_rql const *, tipidee_headers const *) ;
diff --git a/src/tipideed/tipideed.c b/src/tipideed/tipideed.c
index b5098af..402c59c 100644
--- a/src/tipideed/tipideed.c
+++ b/src/tipideed/tipideed.c
@@ -211,12 +211,12 @@ static inline void get_resattr (tipidee_rql const *rql, char const *docroot, cha
static inline void force_redirect (tipidee_rql const *rql, char const *fn)
{
- tipidee_redirection rd = { .sub = 0, .type = 1 } ;
+ tipidee_redirection rd = { .sub = 0, .type = TIPIDEE_REDIR_REDIRECT, .flags = TIPIDEE_REDIR_308, .port = 0 } ;
size_t len = strlen(fn) ;
char location[len + 8 + g.ssl] ;
memcpy(location, g.ssl ? "https://" : "http://", 7 + g.ssl) ;
memcpy(location + 7 + g.ssl, fn, len + 1) ;
- rd.location = location ;
+ rd.addr = location ;
respond_30x(rql, &rd) ;
}
@@ -241,11 +241,13 @@ static inline int serve (tipidee_rql *rql, char const *docroot, char *uribuf, ti
tipidee_redirection rd = TIPIDEE_REDIRECTION_ZERO ;
int e = tipidee_conf_get_redirection(&g.conf, docroot, docrootlen, rql->uri.path, &rd) ;
if (e == -1) die500sys(rql, 111, docroot, "get redirection data for ", fn) ;
- if (e)
+ if (e) switch (rd.type)
{
- if (rd.type & 32) rproxy(rql, &rd, docroot, hdr, body, bodylen) ;
- else respond_30x(rql, &rd) ;
- return 0 ;
+ case TIPIDEE_REDIR_NONE : break ;
+ case TIPIDEE_REDIR_REDIRECT : respond_30x(rql, &rd) ; return 0 ;
+ case TIPIDEE_REDIR_RPROXY : rproxy(rql, &rd, docroot, hdr, body, bodylen) ; return 0 ;
+ case TIPIDEE_REDIR_FASTCGI : fastcgi(rql, &rd, docroot, hdr, body, bodylen) ; return 0 ;
+ default : strerr_dief(101, "can't happen: ", "unknown redirection type") ;
}
}