diff --git a/uppsrc/Skylark/Dispatch.cpp b/uppsrc/Skylark/Dispatch.cpp index b167134e1..667f53322 100644 --- a/uppsrc/Skylark/Dispatch.cpp +++ b/uppsrc/Skylark/Dispatch.cpp @@ -390,13 +390,12 @@ void Http::Dispatch(TcpSocket& socket) } else { r << - "HTTP/1.0 " << code << ' ' << code_text << "\r\n" + "HTTP/1.1 " << code << ' ' << code_text << "\r\n" "Date: " << WwwFormat(GetUtcTime()) << "\r\n" - "Server: U++\r\n" "Content-Length: " << response.GetCount() << "\r\n" - "Connection: close\r\n" - "Cache-Control: no-cache\r\n" "Content-Type: " << content_type << "\r\n"; + for(int i = 0; i < headers.GetCount(); i++) + r << headers.GetKey(i) << ": " << headers[i] << "\r\n"; for(int i = 0; i < cookies.GetCount(); i++) r << cookies[i]; r << "\r\n"; diff --git a/uppsrc/Skylark/Http.cpp b/uppsrc/Skylark/Http.cpp index 8fbd4b619..9ee2d8704 100644 --- a/uppsrc/Skylark/Http.cpp +++ b/uppsrc/Skylark/Http.cpp @@ -12,6 +12,9 @@ Http::Http(SkylarkApp& app) content_type = "text/html; charset=UTF-8"; session_dirty = false; lang = LNG_ENGLISH; + headers.Add("Server","U++"); + headers.Add("Connection","close"); + headers.Add("Cache-Control","no-cache"); } void Http::ParseRequest(const char *p) @@ -121,6 +124,16 @@ Http& Http::SetCookie(const char *id, const String& value, Time expires, return SetRawCookie(id, UrlEncode(value), expires, path, domain, secure); } +Http& Http::SetHeader(const char *header, const char *data) +{ + headers.GetAdd(header) = data; +} + +Http& Http::ClearHeader(const char *header) +{ + headers.RemoveKey(header); +} + void Http::ReadMultiPart(const String& buffer) { const char *p = buffer; diff --git a/uppsrc/Skylark/Http.h b/uppsrc/Skylark/Http.h index 78503f3f8..30773b23d 100644 --- a/uppsrc/Skylark/Http.h +++ b/uppsrc/Skylark/Http.h @@ -56,6 +56,7 @@ class Http : public Renderer { String request_content_type; VectorMap cookies; + VectorMap headers; void ParseRequest(const char *s); void ReadMultiPart(const String& content); @@ -103,6 +104,8 @@ public: Http& SetCookie(const char *id, const String& value, Time expires = Null, const char *path = NULL, const char *domain = NULL, bool secure = false, bool httponly = false); + Http& SetHeader(const char *header, const char *data); + Http& ClearHeader(const char *header); Http& ClearSession(); Http& SessionSet(const char *id, const Value& value); diff --git a/uppsrc/Skylark/Skylark.upt b/uppsrc/Skylark/Skylark.upt index 2b53e7ddd..db2386eec 100644 --- a/uppsrc/Skylark/Skylark.upt +++ b/uppsrc/Skylark/Skylark.upt @@ -9,17 +9,18 @@ select("No database", "MySQL", "Postgres", "Sqlite3") "Database" db = 1; #ifndef _<:PACKAGE:>_<:PACKAGE:>_h #define _<:PACKAGE:>_<:PACKAGE:>_h -#include -<:?db==1:>#include <:?db==2:><:?db==3:>#include -<:.:> +#include <:?db==1:> +#include <:?db==2:> +#include <:?db==3:> +#include <:.:> using namespace Upp; -<:?db:>#define MODEL <<:PACKAGE:>/Model.sch><:.:> -<:?db==1:>#define SCHEMADIALECT <:?db==2:> +<:?db:>#define MODEL <<:PACKAGE:>/Model.sch><:?db==1:> +#define SCHEMADIALECT <:?db==2:> #define SCHEMADIALECT <:?db==3:> -#define SCHEMADIALECT <:.:> -<:?db:>#include <:.:> +#define SCHEMADIALECT <:?db:> +#include <:.:> class <:classname:> : public SkylarkApp { public:<:?db:> @@ -55,8 +56,8 @@ SKYLARK(CatchAll, "**") #include <:.:> <:classname:>::<:classname:>() -{<:?root:> - root = "<:root:>";<:.:> +{ + root = "<:root:>"; #ifdef _DEBUG prefork = 0; use_caching = false; @@ -166,7 +167,7 @@ void <:classname:>::WorkThread() RunThread(); } <:.:> -// After starting the server, enter "127.0.0.1:8001/<:root:>" in your browser +// Local server URL: 127.0.0.1:<:port:>/<:root:> CONSOLE_APP_MAIN { #ifdef _DEBUG diff --git a/uppsrc/Skylark/src.tpp/Http$en-us.tpp b/uppsrc/Skylark/src.tpp/Http$en-us.tpp index cd1739cf0..a93fc598b 100644 --- a/uppsrc/Skylark/src.tpp/Http$en-us.tpp +++ b/uppsrc/Skylark/src.tpp/Http$en-us.tpp @@ -189,6 +189,17 @@ ttp][@(0.0.255) `&]_[* SetCookie]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 id [s2; Same as SetRawCookie, but url`-encoding the [%-*@3 value]. Returns `*this.&] [s3; &] +[s4;%- &] +[s5;:Http`:`:SetHeader`(const char`*`,const char`*`):%- [_^Http^ Http][@(0.0.255) `&]_[* Se +tHeader]([@(0.0.255) const]_[@(0.0.255) char]_`*[*@3 header], [@(0.0.255) const]_[@(0.0.255) c +har]_`*[*@3 data])&] +[s2; Sets the response HTTP [%-*@3 header] value.&] +[s3; &] +[s4;%- &] +[s5;:Http`:`:ClearHeader`(const char`*`):%- [_^Http^ Http][@(0.0.255) `&]_[* ClearHeader]([@(0.0.255) c +onst]_[@(0.0.255) char]_`*[*@3 header])&] +[s2; Removes HTTP [%-*@3 header] from response.&] +[s3; &] [s4; &] [s5;:Http`:`:ClearSession`(`):%- [_^Http^ Http][@(0.0.255) `&]_[* ClearSession]()&] [s2; Clears the session variables and session id (but their values