diff --git a/CMakeLists.txt b/CMakeLists.txt
index d19450f..bfe7983 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -15,6 +15,7 @@ src/Http/HttpClient.cpp
src/Http/HttpStream.cpp
src/Http/ContentDisposition.cpp
src/Http/WebSocket.cpp
+src/Http/ChangeableServer.cpp
src/Mail/Smtp.cpp
src/Serialization/Json.cpp
src/Serialization/SQLite.cpp
diff --git a/examples/webserverex.cpp b/examples/webserverex.cpp
index 2f84a21..840268c 100644
--- a/examples/webserverex.cpp
+++ b/examples/webserverex.cpp
@@ -32,6 +32,22 @@ class MyWebServer : public IHttpServer {
.SendStream(fs);
return true;
}
+ else if(ctx.path == "/mypath.html")
+ {
+ std::string txt = "
Root: " + HttpUtils::HtmlEncode(ctx.GetServerRoot()) + "
";
+ ctx.WithMimeType("text/html").SendText(txt);
+ return true;
+ }
+ else if(ctx.path == "/getabsolute.html")
+ {
+ std::string path;
+ if(ctx.queryParams.TryGetFirst("path",path))
+ {
+ std::string txt = "Path: " + HttpUtils::HtmlEncode(ctx.MakeAbsolute(path)) + "
";
+ ctx.WithMimeType("text/html").SendText(txt);
+ return true;
+ }
+ }
else if(ctx.path == "/streaming.html")
{
StreamWriter writer(ctx.OpenResponseStream());
@@ -109,6 +125,12 @@ class MyOtherWebServer : public IHttpServer
ctx.SendText(data->text);
return true;
}
+ else if(ctx.path == "/mypath.html")
+ {
+ std::string txt = "Root: " + HttpUtils::HtmlEncode(ctx.GetServerRoot()) + "
";
+ ctx.WithMimeType("text/html").SendText(txt);
+ return true;
+ }
return false;
}
diff --git a/include/TessesFramework/Common.hpp b/include/TessesFramework/Common.hpp
index c3575cc..019e63b 100644
--- a/include/TessesFramework/Common.hpp
+++ b/include/TessesFramework/Common.hpp
@@ -43,7 +43,10 @@ namespace Tesses::Framework
mtx.Lock();
for(std::shared_ptr>& item : this->items)
{
- if(item.get() == event.get()) return;
+ if(item.get() == event.get()) {
+ mtx.Unlock();
+ return;
+ }
}
this->items.push_back(event);
mtx.Unlock();
@@ -56,10 +59,11 @@ namespace Tesses::Framework
if(i->get() == event.get())
{
this->items.erase(i);
+ mtx.Unlock();
return;
}
}
- mtx.Lock();
+ mtx.Unlock();
}
void Invoke(TArgs... args)
{
diff --git a/include/TessesFramework/Filesystem/MountableFilesystem.hpp b/include/TessesFramework/Filesystem/MountableFilesystem.hpp
index 5dee18f..22be923 100644
--- a/include/TessesFramework/Filesystem/MountableFilesystem.hpp
+++ b/include/TessesFramework/Filesystem/MountableFilesystem.hpp
@@ -57,6 +57,5 @@ namespace Tesses::Framework::Filesystem
void Chmod(VFSPath path, uint32_t mode);
- void Close();
};
}
\ No newline at end of file
diff --git a/include/TessesFramework/Http/ChangeableServer.hpp b/include/TessesFramework/Http/ChangeableServer.hpp
new file mode 100644
index 0000000..d6d6439
--- /dev/null
+++ b/include/TessesFramework/Http/ChangeableServer.hpp
@@ -0,0 +1,14 @@
+#pragma once
+#include "HttpServer.hpp"
+
+namespace Tesses::Framework::Http
+{
+ class ChangeableServer {
+ public:
+ ChangeableServer();
+ ChangeableServer(std::shared_ptr original);
+ std::shared_ptr server;
+ bool Handle(ServerContext& ctx);
+ ~ChangeableServer();
+ };
+}
\ No newline at end of file
diff --git a/include/TessesFramework/Http/HttpServer.hpp b/include/TessesFramework/Http/HttpServer.hpp
index 17965cf..c2d75db 100644
--- a/include/TessesFramework/Http/HttpServer.hpp
+++ b/include/TessesFramework/Http/HttpServer.hpp
@@ -56,8 +56,15 @@ namespace Tesses::Framework::Http
ServerContext& WithMimeType(std::string mime);
ServerContext& WithContentDisposition(std::string filename, bool isInline);
ServerContext& WriteHeaders();
+ ServerContext& WithLocationHeader(std::string url);
+ ServerContext& WithLocationHeader(std::string url,StatusCode sc);
void StartWebSocketSession(std::function,std::function,std::function)> onOpen, std::function onReceive, std::function onClose);
void StartWebSocketSession(std::shared_ptr connection);
+ std::string GetServerRoot();
+ std::string MakeAbsolute(std::string path);
+ void SendRedirect(std::string url);
+ void SendRedirect(std::string url, StatusCode sc);
+
template
T* GetServerContentData(std::string tag)
diff --git a/include/TessesFramework/Streams/Stream.hpp b/include/TessesFramework/Streams/Stream.hpp
index 0e29229..09ab6ab 100644
--- a/include/TessesFramework/Streams/Stream.hpp
+++ b/include/TessesFramework/Streams/Stream.hpp
@@ -24,6 +24,7 @@ namespace Tesses::Framework::Streams
virtual void Flush();
virtual void Seek(int64_t pos, SeekOrigin whence);
void CopyTo(std::shared_ptr strm, size_t buffSize=1024);
+ void CopyToLimit(std::shared_ptr strm,uint64_t len, size_t buffSize=1024);
virtual void Close();
virtual ~Stream();
};
diff --git a/include/TessesFramework/TessesFramework.hpp b/include/TessesFramework/TessesFramework.hpp
index a5fa039..7daa587 100644
--- a/include/TessesFramework/TessesFramework.hpp
+++ b/include/TessesFramework/TessesFramework.hpp
@@ -6,6 +6,7 @@
#include "Http/CallbackServer.hpp"
#include "Http/MountableServer.hpp"
#include "Http/ContentDisposition.hpp"
+#include "Http/ChangeableServer.hpp"
#include "Streams/FileStream.hpp"
#include "Streams/MemoryStream.hpp"
#include "Streams/NetworkStream.hpp"
diff --git a/src/Filesystem/MountableFilesystem.cpp b/src/Filesystem/MountableFilesystem.cpp
index 9f037b9..4de3600 100644
--- a/src/Filesystem/MountableFilesystem.cpp
+++ b/src/Filesystem/MountableFilesystem.cpp
@@ -21,12 +21,7 @@ namespace Tesses::Framework::Filesystem
for(auto item : this->directories) delete item;
}
- void MountableFilesystem::Close()
- {
- this->root=nullptr;
- for(auto item : this->directories) delete item;
- this->directories.clear();
- }
+
void MountableFilesystem::GetFS(VFSPath srcPath, VFSPath& destRoot, VFSPath& destPath, std::shared_ptr& vfs)
diff --git a/src/Http/ChangeableServer.cpp b/src/Http/ChangeableServer.cpp
new file mode 100644
index 0000000..d3c24e1
--- /dev/null
+++ b/src/Http/ChangeableServer.cpp
@@ -0,0 +1,22 @@
+#include "TessesFramework/Http/ChangeableServer.hpp"
+
+namespace Tesses::Framework::Http {
+ChangeableServer::ChangeableServer() : ChangeableServer(nullptr)
+{
+
+}
+ChangeableServer::ChangeableServer(std::shared_ptr original)
+{
+ this->server = original;
+}
+
+bool ChangeableServer::Handle(ServerContext& ctx)
+{
+ if(this->server) this->server->Handle(ctx);
+ return false;
+}
+ChangeableServer::~ChangeableServer()
+{
+
+}
+}
\ No newline at end of file
diff --git a/src/Http/HttpServer.cpp b/src/Http/HttpServer.cpp
index c6a6cc0..f4c6f0f 100644
--- a/src/Http/HttpServer.cpp
+++ b/src/Http/HttpServer.cpp
@@ -10,6 +10,8 @@
#include "TessesFramework/Threading/Mutex.hpp"
#include "TessesFramework/Common.hpp"
#include "TessesFramework/TextStreams/StdIOWriter.hpp"
+#include "TessesFramework/Filesystem/VFSFix.hpp"
+#include "TessesFramework/Filesystem/VFS.hpp"
#include
using FileStream = Tesses::Framework::Streams::FileStream;
@@ -801,7 +803,7 @@ namespace Tesses::Framework::Http
this->strm->WriteBlock(buffer,read);
begin += read;
- } while(read > 0);
+ } while(read > 0 && !this->strm->EndOfStream());
}
@@ -858,6 +860,26 @@ namespace Tesses::Framework::Http
this->responseHeaders.SetValue("Content-Disposition",cd.ToString());
return *this;
}
+ ServerContext& ServerContext::WithLocationHeader(std::string url)
+ {
+ return WithSingleHeader("Location", this->MakeAbsolute(url));
+ }
+ ServerContext& ServerContext::WithLocationHeader(std::string url,StatusCode sc)
+ {
+ this->statusCode = sc;
+ return WithSingleHeader("Location", this->MakeAbsolute(url));
+ }
+ void ServerContext::SendRedirect(std::string url)
+ {
+ WithLocationHeader(url);
+ this->WriteHeaders();
+ }
+ void ServerContext::SendRedirect(std::string url,StatusCode sc)
+ {
+ WithLocationHeader(url,sc);
+ this->WriteHeaders();
+ }
+
void ServerContext::SendNotFound()
{
if(sent) return;
@@ -1053,5 +1075,22 @@ namespace Tesses::Framework::Http
svr.Start();
thrd.Join();
}
+ std::string ServerContext::GetServerRoot()
+ {
+ if(this->originalPath == this->path) return "/";
+ Tesses::Framework::Filesystem::VFSPath originalPath=this->originalPath;
+ Tesses::Framework::Filesystem::VFSPath path=this->path;
+ if(originalPath.path.size() <= path.path.size()) return "/";
+
+ originalPath.path.resize(originalPath.path.size() - path.path.size());
+ return originalPath.ToString();
+ }
+ std::string ServerContext::MakeAbsolute(std::string path)
+ {
+ if(path.find("http://") == 0 || path.find("https://") == 0 || path.find("/") == 0) return path;
+ Tesses::Framework::Filesystem::VFSPath path2 = GetServerRoot();
+ path2 = path2 / path;
+ return path2.CollapseRelativeParents().ToString();
+ }
}
diff --git a/src/Streams/FileStream.cpp b/src/Streams/FileStream.cpp
index 10b3f39..0bc2a7f 100644
--- a/src/Streams/FileStream.cpp
+++ b/src/Streams/FileStream.cpp
@@ -111,7 +111,7 @@ namespace Tesses::Framework::Streams
if(!f) return;
if(this->owns)
{
- fclose(this->f);
+ fclose(this->f);
f=NULL;
}
}
diff --git a/src/Streams/Stream.cpp b/src/Streams/Stream.cpp
index 45878d1..e7540d2 100644
--- a/src/Streams/Stream.cpp
+++ b/src/Streams/Stream.cpp
@@ -53,7 +53,7 @@ namespace Tesses::Framework::Streams {
buffer += read;
len -= read;
- } while(read > 0);
+ } while(read > 0 && !this->EndOfStream());
}
bool Stream::CanRead()
{
@@ -96,6 +96,27 @@ namespace Tesses::Framework::Streams {
{
}
+
+ void Stream::CopyToLimit(std::shared_ptr strm,uint64_t len, size_t buffSize)
+ {
+ size_t read;
+ uint8_t* buffer = new uint8_t[buffSize];
+ uint64_t offset = 0;
+
+ do {
+ if(offset >= len) break;
+ read = (size_t)std::min(len-offset,(uint64_t)buffSize);
+
+ read = this->Read(buffer,read);
+ strm->WriteBlock(buffer, read);
+
+ offset += read;
+
+ } while(read > 0 && !strm->EndOfStream());
+ strm->Flush();
+
+ delete[] buffer;
+ }
void Stream::CopyTo(std::shared_ptr strm, size_t buffSize)
{
@@ -107,7 +128,7 @@ namespace Tesses::Framework::Streams {
read = this->Read(buffer,buffSize);
strm->WriteBlock(buffer, read);
- } while(read > 0);
+ } while(read > 0 && !strm->EndOfStream());
strm->Flush();
delete[] buffer;