mirror of https://github.com/adamdruppe/arsd.git
timezone
This commit is contained in:
parent
46a3cf2e1e
commit
eae566d0cc
66
cgi.d
66
cgi.d
|
@ -324,6 +324,8 @@ class Cgi {
|
||||||
scriptName = args[0];
|
scriptName = args[0];
|
||||||
scriptFileName = args[0];
|
scriptFileName = args[0];
|
||||||
|
|
||||||
|
environmentVariables = cast(const) environment.toAA;
|
||||||
|
|
||||||
foreach(arg; args[1 .. $]) {
|
foreach(arg; args[1 .. $]) {
|
||||||
if(arg.startsWith("--")) {
|
if(arg.startsWith("--")) {
|
||||||
nextArgIs = arg[2 .. $];
|
nextArgIs = arg[2 .. $];
|
||||||
|
@ -499,6 +501,10 @@ class Cgi {
|
||||||
return *e;
|
return *e;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environmentVariables = env is null ?
|
||||||
|
cast(const) environment.toAA :
|
||||||
|
env;
|
||||||
|
|
||||||
// fetching all the request headers
|
// fetching all the request headers
|
||||||
string[string] requestHeadersHere;
|
string[string] requestHeadersHere;
|
||||||
foreach(k, v; env is null ? cast(const) environment.toAA() : env) {
|
foreach(k, v; env is null ? cast(const) environment.toAA() : env) {
|
||||||
|
@ -1219,6 +1225,7 @@ class Cgi {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
environmentVariables = cast(const) environment.toAA;
|
||||||
|
|
||||||
idlol = inputData;
|
idlol = inputData;
|
||||||
|
|
||||||
|
@ -1266,9 +1273,10 @@ class Cgi {
|
||||||
auto header = cast(string) line.idup;
|
auto header = cast(string) line.idup;
|
||||||
if(headerNumber == 1) {
|
if(headerNumber == 1) {
|
||||||
// request line
|
// request line
|
||||||
auto parts = header.split(" ");
|
auto parts = al.splitter(header, " ");
|
||||||
requestMethod = to!RequestMethod(parts[0]);
|
requestMethod = to!RequestMethod(parts.front);
|
||||||
requestUri = parts[1];
|
parts.popFront();
|
||||||
|
requestUri = parts.front;
|
||||||
|
|
||||||
scriptName = requestUri[0 .. pathInfoStarts];
|
scriptName = requestUri[0 .. pathInfoStarts];
|
||||||
|
|
||||||
|
@ -1359,9 +1367,6 @@ class Cgi {
|
||||||
|
|
||||||
requestHeaders = assumeUnique(requestHeadersHere);
|
requestHeaders = assumeUnique(requestHeadersHere);
|
||||||
|
|
||||||
cookiesArray = getCookieArray();
|
|
||||||
cookies = keepLastOf(cookiesArray);
|
|
||||||
|
|
||||||
ByChunkRange dataByChunk;
|
ByChunkRange dataByChunk;
|
||||||
|
|
||||||
// reading Content-Length type data
|
// reading Content-Length type data
|
||||||
|
@ -1413,6 +1418,10 @@ class Cgi {
|
||||||
this.keepAliveRequested = keepAliveRequested;
|
this.keepAliveRequested = keepAliveRequested;
|
||||||
this.acceptsGzip = acceptsGzip;
|
this.acceptsGzip = acceptsGzip;
|
||||||
this.cookie = cookie;
|
this.cookie = cookie;
|
||||||
|
|
||||||
|
cookiesArray = getCookieArray();
|
||||||
|
cookies = keepLastOf(cookiesArray);
|
||||||
|
|
||||||
}
|
}
|
||||||
BufferedInputRange idlol;
|
BufferedInputRange idlol;
|
||||||
|
|
||||||
|
@ -1543,6 +1552,11 @@ class Cgi {
|
||||||
}
|
}
|
||||||
private string responseStatus = null;
|
private string responseStatus = null;
|
||||||
|
|
||||||
|
/// Returns true if it is still possible to output headers
|
||||||
|
bool canOutputHeaders() {
|
||||||
|
return !isClosed && !outputtedResponseData;
|
||||||
|
}
|
||||||
|
|
||||||
/// Sets the location header, which the browser will redirect the user to automatically.
|
/// Sets the location header, which the browser will redirect the user to automatically.
|
||||||
/// Note setResponseLocation() must be called *before* you write() any data to the output.
|
/// Note setResponseLocation() must be called *before* you write() any data to the output.
|
||||||
/// The optional important argument is used if it's a default suggestion rather than something to insist upon.
|
/// The optional important argument is used if it's a default suggestion rather than something to insist upon.
|
||||||
|
@ -1610,13 +1624,13 @@ class Cgi {
|
||||||
/// Note setCookie() must be called *before* you write() any data to the output.
|
/// Note setCookie() must be called *before* you write() any data to the output.
|
||||||
void setCookie(string name, string data, long expiresIn = 0, string path = null, string domain = null, bool httpOnly = false, bool secure = false) {
|
void setCookie(string name, string data, long expiresIn = 0, string path = null, string domain = null, bool httpOnly = false, bool secure = false) {
|
||||||
assert(!outputtedResponseData);
|
assert(!outputtedResponseData);
|
||||||
string cookie = name ~ "=";
|
string cookie = std.uri.encodeComponent(name) ~ "=";
|
||||||
cookie ~= data;
|
cookie ~= std.uri.encodeComponent(data);
|
||||||
if(path !is null)
|
if(path !is null)
|
||||||
cookie ~= "; path=" ~ path;
|
cookie ~= "; path=" ~ path;
|
||||||
// FIXME: should I just be using max-age here? (also in cache below)
|
// FIXME: should I just be using max-age here? (also in cache below)
|
||||||
if(expiresIn != 0)
|
if(expiresIn != 0)
|
||||||
cookie ~= "; expires=" ~ printDate(cast(DateTime) Clock.currTime + dur!"msecs"(expiresIn));
|
cookie ~= "; expires=" ~ printDate(cast(DateTime) Clock.currTime(UTC()) + dur!"msecs"(expiresIn));
|
||||||
if(domain !is null)
|
if(domain !is null)
|
||||||
cookie ~= "; domain=" ~ domain;
|
cookie ~= "; domain=" ~ domain;
|
||||||
if(secure == true)
|
if(secure == true)
|
||||||
|
@ -1624,9 +1638,15 @@ class Cgi {
|
||||||
if(httpOnly == true )
|
if(httpOnly == true )
|
||||||
cookie ~= "; HttpOnly";
|
cookie ~= "; HttpOnly";
|
||||||
|
|
||||||
responseCookies ~= cookie;
|
if(auto idx = name in cookieIndexes) {
|
||||||
|
responseCookies[*idx] = cookie;
|
||||||
|
} else {
|
||||||
|
cookieIndexes[name] = responseCookies.length;
|
||||||
|
responseCookies ~= cookie;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
private string[] responseCookies;
|
private string[] responseCookies;
|
||||||
|
private int[string] cookieIndexes;
|
||||||
|
|
||||||
/// Clears a previously set cookie with the given name, path, and domain.
|
/// Clears a previously set cookie with the given name, path, and domain.
|
||||||
void clearCookie(string name, string path = null, string domain = null) {
|
void clearCookie(string name, string path = null, string domain = null) {
|
||||||
|
@ -1674,7 +1694,7 @@ class Cgi {
|
||||||
goto websocket;
|
goto websocket;
|
||||||
|
|
||||||
if(nph) { // we're responsible for setting the date too according to http 1.1
|
if(nph) { // we're responsible for setting the date too according to http 1.1
|
||||||
hd ~= "Date: " ~ printDate(cast(DateTime) Clock.currTime);
|
hd ~= "Date: " ~ printDate(cast(DateTime) Clock.currTime(UTC()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: what if the user wants to set his own content-length?
|
// FIXME: what if the user wants to set his own content-length?
|
||||||
|
@ -1921,6 +1941,8 @@ class Cgi {
|
||||||
private bool outputtedResponseData;
|
private bool outputtedResponseData;
|
||||||
private bool noCache = true;
|
private bool noCache = true;
|
||||||
|
|
||||||
|
const(string[string]) environmentVariables;
|
||||||
|
|
||||||
/** What follows is data gotten from the HTTP request. It is all fully immutable,
|
/** What follows is data gotten from the HTTP request. It is all fully immutable,
|
||||||
partially because it logically is (your code doesn't change what the user requested...)
|
partially because it logically is (your code doesn't change what the user requested...)
|
||||||
and partially because I hate how bad programs in PHP change those superglobals to do
|
and partially because I hate how bad programs in PHP change those superglobals to do
|
||||||
|
@ -2468,7 +2490,7 @@ mixin template CustomCgiMain(CustomCgi, alias fun, long maxContentLength = defau
|
||||||
throw new Exception("bind");
|
throw new Exception("bind");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sock.listen(16) == -1) {
|
if(sock.listen(128) == -1) {
|
||||||
close(sock);
|
close(sock);
|
||||||
throw new Exception("listen");
|
throw new Exception("listen");
|
||||||
}
|
}
|
||||||
|
@ -2482,6 +2504,7 @@ mixin template CustomCgiMain(CustomCgi, alias fun, long maxContentLength = defau
|
||||||
newPid = fork();
|
newPid = fork();
|
||||||
if(newPid == 0) {
|
if(newPid == 0) {
|
||||||
// start serving on the socket
|
// start serving on the socket
|
||||||
|
//ubyte[4096] backingBuffer;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
bool closeConnection;
|
bool closeConnection;
|
||||||
uint i;
|
uint i;
|
||||||
|
@ -2491,12 +2514,17 @@ mixin template CustomCgiMain(CustomCgi, alias fun, long maxContentLength = defau
|
||||||
|
|
||||||
if(s == -1)
|
if(s == -1)
|
||||||
throw new Exception("accept");
|
throw new Exception("accept");
|
||||||
|
//ubyte[__traits(classInstanceSize, BufferedInputRange)] bufferedRangeContainer;
|
||||||
auto ir = new BufferedInputRange(s);
|
auto ir = new BufferedInputRange(s);
|
||||||
|
//auto ir = emplace!BufferedInputRange(bufferedRangeContainer, s, backingBuffer);
|
||||||
|
|
||||||
while(!ir.empty) {
|
while(!ir.empty) {
|
||||||
|
ubyte[__traits(classInstanceSize, CustomCgi)] cgiContainer;
|
||||||
|
|
||||||
Cgi cgi;
|
Cgi cgi;
|
||||||
try {
|
try {
|
||||||
cgi = new CustomCgi(ir, &closeConnection);
|
cgi = new CustomCgi(ir, &closeConnection);
|
||||||
|
//cgi = emplace!CustomCgi(cgiContainer, ir, &closeConnection);
|
||||||
} catch(Throwable t) {
|
} catch(Throwable t) {
|
||||||
// a construction error is either bad code or bad request; bad request is what it should be since this is bug free :P
|
// a construction error is either bad code or bad request; bad request is what it should be since this is bug free :P
|
||||||
// anyway let's kill the connection
|
// anyway let's kill the connection
|
||||||
|
@ -2541,6 +2569,7 @@ mixin template CustomCgiMain(CustomCgi, alias fun, long maxContentLength = defau
|
||||||
int status;
|
int status;
|
||||||
// FIXME: maybe we should respawn if one dies unexpectedly
|
// FIXME: maybe we should respawn if one dies unexpectedly
|
||||||
while(-1 != wait(&status)) {
|
while(-1 != wait(&status)) {
|
||||||
|
import std.stdio; writeln("Process died ", status);
|
||||||
processCount--;
|
processCount--;
|
||||||
goto reopen;
|
goto reopen;
|
||||||
}
|
}
|
||||||
|
@ -3011,9 +3040,16 @@ class BufferedInputRange {
|
||||||
|
|
||||||
do {
|
do {
|
||||||
auto freeSpace = underlyingBuffer[underlyingBuffer.ptr - view.ptr + view.length .. $];
|
auto freeSpace = underlyingBuffer[underlyingBuffer.ptr - view.ptr + view.length .. $];
|
||||||
|
try_again:
|
||||||
auto ret = source.receive(freeSpace);
|
auto ret = source.receive(freeSpace);
|
||||||
if(ret == Socket.ERROR)
|
if(ret == Socket.ERROR) {
|
||||||
throw new Exception("uh oh"); // FIXME
|
version(Posix) {
|
||||||
|
import core.stdc.errno;
|
||||||
|
if(errno == EINTR)
|
||||||
|
goto try_again;
|
||||||
|
}
|
||||||
|
throw new Exception("uh oh " ~ lastSocketError); // FIXME
|
||||||
|
}
|
||||||
if(ret == 0) {
|
if(ret == 0) {
|
||||||
sourceClosed = true;
|
sourceClosed = true;
|
||||||
return;
|
return;
|
||||||
|
@ -3138,7 +3174,7 @@ class ListeningConnectionManager {
|
||||||
listener = new TcpSocket();
|
listener = new TcpSocket();
|
||||||
listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
|
listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
|
||||||
listener.bind(new InternetAddress(port));
|
listener.bind(new InternetAddress(port));
|
||||||
listener.listen(10);
|
listener.listen(128);
|
||||||
}
|
}
|
||||||
|
|
||||||
Socket listener;
|
Socket listener;
|
||||||
|
|
Loading…
Reference in New Issue