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,
|
this(long maxContentLength = 5_000_000,
|
||||||
string[string] env = null,
|
string[string] env = null,
|
||||||
const(ubyte)[] delegate() readdata = null,
|
const(ubyte)[] delegate() readdata = null,
|
||||||
void delegate(const(ubyte)[]) _rawDataOutput = null
|
void delegate(const(ubyte)[]) _rawDataOutput = null,
|
||||||
) { super(maxContentLength, env, readdata, _rawDataOutput); }
|
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) {
|
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);
|
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
|
// and this should return a chunk of data. return empty when done
|
||||||
const(ubyte)[] delegate() readdata = null,
|
const(ubyte)[] delegate() readdata = null,
|
||||||
// finally, use this to do custom output if needed
|
// 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;
|
rawDataOutput = _rawDataOutput;
|
||||||
|
flushDelegate = _flush;
|
||||||
auto getenv = delegate string(string var) {
|
auto getenv = delegate string(string var) {
|
||||||
if(env is null)
|
if(env is null)
|
||||||
return .getenv(var);
|
return .getenv(var);
|
||||||
|
@ -743,13 +747,14 @@ class Cgi {
|
||||||
indeed, it should probably just take a file descriptor
|
indeed, it should probably just take a file descriptor
|
||||||
or two and do all the work itself.
|
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(" ");
|
auto parts = headers[0].split(" ");
|
||||||
|
|
||||||
https = false;
|
https = false;
|
||||||
port = 80; // FIXME
|
port = 80; // FIXME
|
||||||
|
|
||||||
rawDataOutput = _rawDataOutput;
|
rawDataOutput = _rawDataOutput;
|
||||||
|
flushDelegate = _flush;
|
||||||
nph = true;
|
nph = true;
|
||||||
|
|
||||||
requestMethod = to!RequestMethod(parts[0]);
|
requestMethod = to!RequestMethod(parts[0]);
|
||||||
|
@ -773,7 +778,7 @@ class Cgi {
|
||||||
|
|
||||||
remoteAddress = address;
|
remoteAddress = address;
|
||||||
|
|
||||||
if(headers[0].indexOf("HTTP/1.0")) {
|
if(headers[0].indexOf("HTTP/1.0") != -1) {
|
||||||
http10 = true;
|
http10 = true;
|
||||||
autoBuffer = true;
|
autoBuffer = true;
|
||||||
}
|
}
|
||||||
|
@ -1219,7 +1224,8 @@ class Cgi {
|
||||||
void flush() {
|
void flush() {
|
||||||
if(rawDataOutput is null)
|
if(rawDataOutput is null)
|
||||||
stdout.flush();
|
stdout.flush();
|
||||||
// FIXME: also flush to other sources
|
else if(flushDelegate !is null)
|
||||||
|
flushDelegate();
|
||||||
}
|
}
|
||||||
|
|
||||||
version(autoBuffer)
|
version(autoBuffer)
|
||||||
|
@ -1274,6 +1280,7 @@ class Cgi {
|
||||||
|
|
||||||
/* Hooks for redirecting input and output */
|
/* Hooks for redirecting input and output */
|
||||||
private void delegate(const(ubyte)[]) rawDataOutput = null;
|
private void delegate(const(ubyte)[]) rawDataOutput = null;
|
||||||
|
private void delegate() flushDelegate = null;
|
||||||
|
|
||||||
/* This info is used when handling a more raw HTTP protocol */
|
/* This info is used when handling a more raw HTTP protocol */
|
||||||
private bool nph;
|
private bool nph;
|
||||||
|
@ -1590,7 +1597,11 @@ version(embedded_httpd)
|
||||||
return "";
|
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 {
|
try {
|
||||||
fun(cgi);
|
fun(cgi);
|
||||||
cgi.close();
|
cgi.close();
|
||||||
|
@ -1741,6 +1752,8 @@ version(fastcgi) {
|
||||||
int FCGX_GetChar(FCGX_Stream* stream);
|
int FCGX_GetChar(FCGX_Stream* stream);
|
||||||
int FCGX_PutStr(const ubyte* str, int n, FCGX_Stream* stream);
|
int FCGX_PutStr(const ubyte* str, int n, FCGX_Stream* stream);
|
||||||
int FCGX_HasSeenEOF(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 {
|
try {
|
||||||
cgi = new CustomCgi(headers, data, peerAddress(),
|
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) {
|
} catch(Throwable t) {
|
||||||
write("HTTP/1.1 400 Bad Request\r\n");
|
write("HTTP/1.1 400 Bad Request\r\n");
|
||||||
write("Content-Type: text/plain\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
|
//events to handle: data ready to read, timeout, new connection, connection error
|
||||||
// stuff to do: write data
|
// stuff to do: write data
|
||||||
|
|
||||||
|
try_again:
|
||||||
|
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
fd_set writefs;
|
fd_set writefs;
|
||||||
timeval tv;
|
timeval tv;
|
||||||
|
@ -207,8 +209,14 @@ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, on.sizeof);
|
||||||
else
|
else
|
||||||
ret = linux.select(biggest + 1, &rdfs, &writefs, null, &tv);
|
ret = linux.select(biggest + 1, &rdfs, &writefs, null, &tv);
|
||||||
|
|
||||||
if(ret == -1)
|
if(ret == -1) {
|
||||||
throw new Exception("select");
|
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) {
|
if(ret) {
|
||||||
// data ready somewhere
|
// 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
|
// Writes the pending data to the socket now instead of waiting for the manager to proceed
|
||||||
void flush(){
|
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.
|
// reads the requested amount now, blocking until you get it all.
|
||||||
|
|
Loading…
Reference in New Issue