mirror of https://github.com/adamdruppe/arsd.git
lots of embedded httpd fixes
This commit is contained in:
parent
bedea1ec31
commit
491434c645
31
cgi.d
31
cgi.d
|
@ -48,11 +48,12 @@ mixin template ForwardCgiConstructors() {
|
|||
this(long maxContentLength = 5_000_000,
|
||||
string[string] env = null,
|
||||
const(ubyte)[] delegate() readdata = null,
|
||||
void delegate(const(ubyte)[]) _rawDataOutput = null
|
||||
) { super(maxContentLength, env, readdata, _rawDataOutput); }
|
||||
void delegate(const(ubyte)[]) _rawDataOutput = null,
|
||||
void delegate() _flush = null
|
||||
) { super(maxContentLength, env, readdata, _rawDataOutput, _flush); }
|
||||
|
||||
this(string[] headers, immutable(ubyte)[] data, string address, void delegate(const(ubyte)[]) _rawDataOutput = null, int pathInfoStarts = 0) {
|
||||
super(headers, data, address, _rawDataOutput, pathInfoStarts);
|
||||
this(string[] headers, immutable(ubyte)[] data, string address, void delegate(const(ubyte)[]) _rawDataOutput = null, int pathInfoStarts = 0, void delegate() _flush = null) {
|
||||
super(headers, data, address, _rawDataOutput, pathInfoStarts, _flush);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,10 +143,13 @@ class Cgi {
|
|||
// and this should return a chunk of data. return empty when done
|
||||
const(ubyte)[] delegate() readdata = null,
|
||||
// finally, use this to do custom output if needed
|
||||
void delegate(const(ubyte)[]) _rawDataOutput = null
|
||||
void delegate(const(ubyte)[]) _rawDataOutput = null,
|
||||
// to flush teh custom output
|
||||
void delegate() _flush = null
|
||||
)
|
||||
{
|
||||
rawDataOutput = _rawDataOutput;
|
||||
flushDelegate = _flush;
|
||||
auto getenv = delegate string(string var) {
|
||||
if(env is null)
|
||||
return .getenv(var);
|
||||
|
@ -743,13 +747,14 @@ class Cgi {
|
|||
indeed, it should probably just take a file descriptor
|
||||
or two and do all the work itself.
|
||||
*/
|
||||
this(string[] headers, immutable(ubyte)[] data, string address, void delegate(const(ubyte)[]) _rawDataOutput = null, int pathInfoStarts = 0) {
|
||||
this(string[] headers, immutable(ubyte)[] data, string address, void delegate(const(ubyte)[]) _rawDataOutput = null, int pathInfoStarts = 0, void delegate() _flush = null) {
|
||||
auto parts = headers[0].split(" ");
|
||||
|
||||
https = false;
|
||||
port = 80; // FIXME
|
||||
|
||||
rawDataOutput = _rawDataOutput;
|
||||
flushDelegate = _flush;
|
||||
nph = true;
|
||||
|
||||
requestMethod = to!RequestMethod(parts[0]);
|
||||
|
@ -773,7 +778,7 @@ class Cgi {
|
|||
|
||||
remoteAddress = address;
|
||||
|
||||
if(headers[0].indexOf("HTTP/1.0")) {
|
||||
if(headers[0].indexOf("HTTP/1.0") != -1) {
|
||||
http10 = true;
|
||||
autoBuffer = true;
|
||||
}
|
||||
|
@ -1219,7 +1224,8 @@ class Cgi {
|
|||
void flush() {
|
||||
if(rawDataOutput is null)
|
||||
stdout.flush();
|
||||
// FIXME: also flush to other sources
|
||||
else if(flushDelegate !is null)
|
||||
flushDelegate();
|
||||
}
|
||||
|
||||
version(autoBuffer)
|
||||
|
@ -1274,6 +1280,7 @@ class Cgi {
|
|||
|
||||
/* Hooks for redirecting input and output */
|
||||
private void delegate(const(ubyte)[]) rawDataOutput = null;
|
||||
private void delegate() flushDelegate = null;
|
||||
|
||||
/* This info is used when handling a more raw HTTP protocol */
|
||||
private bool nph;
|
||||
|
@ -1590,7 +1597,11 @@ version(embedded_httpd)
|
|||
return "";
|
||||
}
|
||||
|
||||
auto cgi = new CustomCgi(5_000_000, fcgienv, &getFcgiChunk, &writeFcgi);
|
||||
void flushFcgi() {
|
||||
FCGX_FFlush(output);
|
||||
}
|
||||
|
||||
auto cgi = new CustomCgi(5_000_000, fcgienv, &getFcgiChunk, &writeFcgi, &flushFcgi);
|
||||
try {
|
||||
fun(cgi);
|
||||
cgi.close();
|
||||
|
@ -1741,6 +1752,8 @@ version(fastcgi) {
|
|||
int FCGX_GetChar(FCGX_Stream* stream);
|
||||
int FCGX_PutStr(const ubyte* str, int n, FCGX_Stream* stream);
|
||||
int FCGX_HasSeenEOF(FCGX_Stream* stream);
|
||||
int FCGX_FFlush(FCGX_Stream *stream);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
2
httpd.d
2
httpd.d
|
@ -90,7 +90,7 @@ class HttpdConnection(CustomCgi) : Connection /* if(is(CustomCgi : Cgi)) */ {
|
|||
|
||||
try {
|
||||
cgi = new CustomCgi(headers, data, peerAddress(),
|
||||
cast(void delegate(const(ubyte)[])) &this.write);
|
||||
cast(void delegate(const(ubyte)[])) &this.write, 0, &this.flush);
|
||||
} catch(Throwable t) {
|
||||
write("HTTP/1.1 400 Bad Request\r\n");
|
||||
write("Content-Type: text/plain\r\n");
|
||||
|
|
26
netman.d
26
netman.d
|
@ -170,6 +170,8 @@ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, on.sizeof);
|
|||
//events to handle: data ready to read, timeout, new connection, connection error
|
||||
// stuff to do: write data
|
||||
|
||||
try_again:
|
||||
|
||||
fd_set rdfs;
|
||||
fd_set writefs;
|
||||
timeval tv;
|
||||
|
@ -207,8 +209,14 @@ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, on.sizeof);
|
|||
else
|
||||
ret = linux.select(biggest + 1, &rdfs, &writefs, null, &tv);
|
||||
|
||||
if(ret == -1)
|
||||
throw new Exception("select");
|
||||
if(ret == -1) {
|
||||
import core.stdc.errno;
|
||||
import std.conv;
|
||||
if(errno == 4) // interrupted by signal
|
||||
goto try_again;
|
||||
else
|
||||
throw new Exception("select " ~ to!string(errno));
|
||||
}
|
||||
|
||||
if(ret) {
|
||||
// data ready somewhere
|
||||
|
@ -369,7 +377,21 @@ class Connection {
|
|||
|
||||
// Writes the pending data to the socket now instead of waiting for the manager to proceed
|
||||
void flush(){
|
||||
if(writeBufferLength > 0) {
|
||||
auto b = writeBuffer[writeBufferPosition..(writeBufferPosition+writeBufferLength)];
|
||||
auto num = .write(socket, b.ptr, b.length);
|
||||
if(num < 0)
|
||||
throw new ConnectionException("send", this);
|
||||
|
||||
writeBufferLength -= num;
|
||||
if(writeBufferLength > 0)
|
||||
writeBufferPosition += num;
|
||||
else
|
||||
writeBufferPosition = 0;
|
||||
|
||||
timeOfLastActivity = now;
|
||||
fsync(socket);
|
||||
}
|
||||
}
|
||||
|
||||
// reads the requested amount now, blocking until you get it all.
|
||||
|
|
Loading…
Reference in New Issue