mirror of https://github.com/vitalif/phantomjs
extend WebServerResponse API
parent
705eda8823
commit
a6bde751a9
|
@ -24,14 +24,16 @@ if (phantom.args.length !== 1) {
|
||||||
console.log("request.headerValue(" + i + ") = " + request.headerValue(i));
|
console.log("request.headerValue(" + i + ") = " + request.headerValue(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
var headers = "HTTP/1.1 200 OK\r\n" +
|
// we set the headers here
|
||||||
"Cache: no-cache\r\n" +
|
response.statusCode = 200;
|
||||||
"Content-Type: text/html\r\n" +
|
response.headers = {"Cache": "no-cache", "Content-Type": "text/html"};
|
||||||
"\r\n";
|
// this is also possible:
|
||||||
response.writeHeaders(headers);
|
response.setHeader("foo", "bar");
|
||||||
var contents = "<html><head><title>YES!</title></head>" +
|
// now we write the body
|
||||||
"<body><p>pretty cool :)</body></html>";
|
// note: the headers above will now be sent implictly
|
||||||
response.writeBody(contents);
|
response.writeBody("<html><head><title>YES!</title></head>");
|
||||||
|
// note: writeBody can be called multiple times
|
||||||
|
response.writeBody("<body><p>pretty cool :)</body></html>");
|
||||||
});
|
});
|
||||||
var url = "http://localhost:" + port + "/foo/bar.php?asdf=true";
|
var url = "http://localhost:" + port + "/foo/bar.php?asdf=true";
|
||||||
console.log(url);
|
console.log(url);
|
||||||
|
|
|
@ -183,19 +183,161 @@ QString WebServerRequest::headerValue(int header) const
|
||||||
|
|
||||||
WebServerResponse::WebServerResponse(mg_connection *conn)
|
WebServerResponse::WebServerResponse(mg_connection *conn)
|
||||||
: m_conn(conn)
|
: m_conn(conn)
|
||||||
|
, m_statusCode(200)
|
||||||
|
, m_headersSent(false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebServerResponse::writeHeaders(const QString &headers)
|
const char* responseCodeString(int code)
|
||||||
{
|
{
|
||||||
mg_printf(m_conn, "%s", qPrintable(headers));
|
// see: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||||
|
switch (code) {
|
||||||
|
case 100:
|
||||||
|
return "Continue";
|
||||||
|
case 101:
|
||||||
|
return "Switching Protocols";
|
||||||
|
case 200:
|
||||||
|
return "OK";
|
||||||
|
case 201:
|
||||||
|
return "Created";
|
||||||
|
case 202:
|
||||||
|
return "Accepted";
|
||||||
|
case 203:
|
||||||
|
return "Non-Authoritative Information";
|
||||||
|
case 204:
|
||||||
|
return "No Content";
|
||||||
|
case 205:
|
||||||
|
return "Reset Content";
|
||||||
|
case 206:
|
||||||
|
return "Partial Content";
|
||||||
|
case 300:
|
||||||
|
return "Multiple Choices";
|
||||||
|
case 301:
|
||||||
|
return "Moved Permanently";
|
||||||
|
case 302:
|
||||||
|
return "Found";
|
||||||
|
case 303:
|
||||||
|
return "See Other";
|
||||||
|
case 304:
|
||||||
|
return "Not Modified";
|
||||||
|
case 305:
|
||||||
|
return "Use Proxy";
|
||||||
|
case 307:
|
||||||
|
return "Temporary Redirect";
|
||||||
|
case 400:
|
||||||
|
return "Bad Request";
|
||||||
|
case 401:
|
||||||
|
return "Unauthorized";
|
||||||
|
case 402:
|
||||||
|
return "Payment Required";
|
||||||
|
case 403:
|
||||||
|
return "Forbidden";
|
||||||
|
case 404:
|
||||||
|
return "Not Found";
|
||||||
|
case 405:
|
||||||
|
return "Method Not Allowed";
|
||||||
|
case 406:
|
||||||
|
return "Not Acceptable";
|
||||||
|
case 407:
|
||||||
|
return "Proxy Authentication Required";
|
||||||
|
case 408:
|
||||||
|
return "Request Timeout";
|
||||||
|
case 409:
|
||||||
|
return "Conflict";
|
||||||
|
case 410:
|
||||||
|
return "Gone";
|
||||||
|
case 411:
|
||||||
|
return "Length Required";
|
||||||
|
case 412:
|
||||||
|
return "Precondition Failed";
|
||||||
|
case 413:
|
||||||
|
return "Request Entity Too Large";
|
||||||
|
case 414:
|
||||||
|
return "Request-URI Too Long";
|
||||||
|
case 415:
|
||||||
|
return "Unsupported Media Type";
|
||||||
|
case 416:
|
||||||
|
return "Requested Range not Satisfiable";
|
||||||
|
case 417:
|
||||||
|
return "Expectation Failed";
|
||||||
|
case 500:
|
||||||
|
return "Internal Server Error";
|
||||||
|
case 501:
|
||||||
|
return "Not Implemented";
|
||||||
|
case 502:
|
||||||
|
return "Bad Gateway";
|
||||||
|
case 503:
|
||||||
|
return "Service Unavailable";
|
||||||
|
case 504:
|
||||||
|
return "Gateway Timeout";
|
||||||
|
case 505:
|
||||||
|
return "HTTP Version Not Supported";
|
||||||
|
case 306:
|
||||||
|
// unused: fallthrough
|
||||||
|
default:
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServerResponse::writeHeaders(int statusCode, const QVariantMap &headers)
|
||||||
|
{
|
||||||
|
///TODO: what is the best-practice error handling in javascript? exceptions?
|
||||||
|
Q_ASSERT(!m_headersSent);
|
||||||
|
m_headersSent = true;
|
||||||
|
mg_printf(m_conn, "HTTP/1.1 %d %s\r\n", m_statusCode, responseCodeString(m_statusCode));
|
||||||
|
QVariantMap::const_iterator it = headers.constBegin();
|
||||||
|
while(it != headers.constEnd()) {
|
||||||
|
mg_printf(m_conn, "%s: %s\r\n", qPrintable(it.key()), qPrintable(it.value().toString()));
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
mg_write(m_conn, "\r\n", 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebServerResponse::writeBody(const QString &body)
|
void WebServerResponse::writeBody(const QString &body)
|
||||||
{
|
{
|
||||||
mg_printf(m_conn, "%s", qPrintable(body));
|
if (!m_headersSent) {
|
||||||
|
writeHeaders(m_statusCode, m_headers);
|
||||||
|
}
|
||||||
|
///TODO: encoding?!
|
||||||
|
const QByteArray data = body.toLocal8Bit();
|
||||||
|
mg_write(m_conn, data.constData(), data.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int WebServerResponse::statusCode() const
|
||||||
|
{
|
||||||
|
return m_statusCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServerResponse::setStatusCode(int code)
|
||||||
|
{
|
||||||
|
///TODO: what is the best-practice error handling in javascript? exceptions?
|
||||||
|
Q_ASSERT(!m_headersSent);
|
||||||
|
m_statusCode = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString WebServerResponse::header(const QString &name) const
|
||||||
|
{
|
||||||
|
return m_headers.value(name).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServerResponse::setHeader(const QString &name, const QString &value)
|
||||||
|
{
|
||||||
|
///TODO: what is the best-practice error handling in javascript? exceptions?
|
||||||
|
Q_ASSERT(!m_headersSent);
|
||||||
|
m_headers.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariantMap WebServerResponse::headers() const
|
||||||
|
{
|
||||||
|
return m_headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WebServerResponse::setHeaders(const QVariantMap &headers)
|
||||||
|
{
|
||||||
|
///TODO: what is the best-practice error handling in javascript? exceptions?
|
||||||
|
Q_ASSERT(!m_headersSent);
|
||||||
|
m_headers = headers;
|
||||||
|
}
|
||||||
|
|
||||||
//END WebServerResponse
|
//END WebServerResponse
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define WEBSERVER_H
|
#define WEBSERVER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
///TODO: is this ok, or should it be put into .cpp
|
///TODO: is this ok, or should it be put into .cpp
|
||||||
/// can be done by introducing a WebServerPrivate *d;
|
/// can be done by introducing a WebServerPrivate *d;
|
||||||
|
@ -110,17 +111,37 @@ class WebServerResponse : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY(int statusCode READ statusCode WRITE setStatusCode);
|
||||||
|
Q_PROPERTY(QVariantMap headers READ headers WRITE setHeaders);
|
||||||
public:
|
public:
|
||||||
WebServerResponse(mg_connection *conn);
|
WebServerResponse(mg_connection *conn);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
///TODO: improve API
|
///TODO: improve API
|
||||||
void writeHeaders(const QString& headers);
|
void writeHeaders(int statusCode, const QVariantMap &headers);
|
||||||
///TODO: implictly write default headers if not called yet
|
/// sends @p data to client and makes sure the headers are send beforehand
|
||||||
void writeBody(const QString& body);
|
void writeBody(const QString &data);
|
||||||
|
|
||||||
|
/// get the currently set status code, 200 is the default
|
||||||
|
int statusCode() const;
|
||||||
|
/// set the status code to @p code
|
||||||
|
void setStatusCode(int code);
|
||||||
|
|
||||||
|
/// get the value of header @p name
|
||||||
|
QString header(const QString &name) const;
|
||||||
|
/// set the value of header @p name to @p value
|
||||||
|
void setHeader(const QString &name, const QString &value);
|
||||||
|
|
||||||
|
/// get all headers
|
||||||
|
QVariantMap headers() const;
|
||||||
|
/// set all headers
|
||||||
|
void setHeaders(const QVariantMap &headers);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mg_connection *m_conn;
|
mg_connection *m_conn;
|
||||||
|
int m_statusCode;
|
||||||
|
QVariantMap m_headers;
|
||||||
|
bool m_headersSent;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // WEBSERVER_H
|
#endif // WEBSERVER_H
|
||||||
|
|
Loading…
Reference in New Issue