switch back to boost::filesystem to avoid the requirement of c++17
This commit is contained in:
+2
-2
@@ -41,14 +41,14 @@ if(WIN32)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
# C++ standard requirements.
|
# C++ standard requirements.
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
# Boost
|
# Boost
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
set(Boost_USE_MULTITHREADED ON)
|
||||||
find_package(Boost 1.66.0 REQUIRED COMPONENTS system date_time)
|
find_package(Boost 1.66.0 REQUIRED COMPONENTS system date_time filesystem)
|
||||||
if(Boost_FOUND)
|
if(Boost_FOUND)
|
||||||
message(STATUS "Boost version: ${Boost_VERSION}")
|
message(STATUS "Boost version: ${Boost_VERSION}")
|
||||||
include_directories(${Boost_INCLUDE_DIRS})
|
include_directories(${Boost_INCLUDE_DIRS})
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
[__中文版 README__](README_zh_CN.md)
|
[__中文版 README__](README_zh_CN.md)
|
||||||
|
|
||||||
Lightweight C++ HTTP __client and server__ library based on [Asio](https://www.boost.org/doc/libs/release/libs/asio/) for __embedding__ purpose.
|
Lightweight C++ HTTP __client and server__ library based on [Boost Asio](https://www.boost.org/doc/libs/release/libs/asio/) for __embedding__ purpose.
|
||||||
|
|
||||||
=> [Build Instructions](doc/Build-Instructions.md)
|
=> [Build Instructions](doc/Build-Instructions.md)
|
||||||
|
|
||||||
|
|||||||
+18
-17
@@ -1,7 +1,9 @@
|
|||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "boost/filesystem/fstream.hpp"
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
@@ -9,7 +11,7 @@
|
|||||||
#include "webcc/client_session.h"
|
#include "webcc/client_session.h"
|
||||||
#include "webcc/string.h"
|
#include "webcc/string.h"
|
||||||
|
|
||||||
namespace sfs = std::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -194,15 +196,15 @@ TEST(ClientTest, Get_Jpeg_Stream) {
|
|||||||
EXPECT_TRUE(!file_body->path().empty());
|
EXPECT_TRUE(!file_body->path().empty());
|
||||||
|
|
||||||
// Backup the path of the temp file.
|
// Backup the path of the temp file.
|
||||||
const sfs::path ori_path = file_body->path();
|
const bfs::path ori_path = file_body->path();
|
||||||
|
|
||||||
const sfs::path new_path("./wolf.jpeg");
|
const bfs::path new_path("./wolf.jpeg");
|
||||||
|
|
||||||
bool moved = file_body->Move(new_path);
|
bool moved = file_body->Move(new_path);
|
||||||
EXPECT_TRUE(moved);
|
EXPECT_TRUE(moved);
|
||||||
EXPECT_TRUE(sfs::exists(new_path));
|
EXPECT_TRUE(bfs::exists(new_path));
|
||||||
// The file in the original path should not exist any more.
|
// The file in the original path should not exist any more.
|
||||||
EXPECT_TRUE(!sfs::exists(ori_path));
|
EXPECT_TRUE(!bfs::exists(ori_path));
|
||||||
|
|
||||||
// After move, the original path should be reset.
|
// After move, the original path should be reset.
|
||||||
EXPECT_TRUE(file_body->path().empty());
|
EXPECT_TRUE(file_body->path().empty());
|
||||||
@@ -218,7 +220,7 @@ TEST(ClientTest, Get_Jpeg_Stream_NoMove) {
|
|||||||
webcc::ClientSession session;
|
webcc::ClientSession session;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
sfs::path ori_path;
|
bfs::path ori_path;
|
||||||
|
|
||||||
{
|
{
|
||||||
auto r = session.Send(webcc::RequestBuilder{}.
|
auto r = session.Send(webcc::RequestBuilder{}.
|
||||||
@@ -236,7 +238,7 @@ TEST(ClientTest, Get_Jpeg_Stream_NoMove) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The temp file should be deleted.
|
// The temp file should be deleted.
|
||||||
EXPECT_TRUE(!sfs::exists(ori_path));
|
EXPECT_TRUE(!bfs::exists(ori_path));
|
||||||
|
|
||||||
} catch (const webcc::Error& error) {
|
} catch (const webcc::Error& error) {
|
||||||
std::cerr << error << std::endl;
|
std::cerr << error << std::endl;
|
||||||
@@ -309,23 +311,22 @@ TEST(ClientTest, Post) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static sfs::path GenerateTempFile(const std::string& data) {
|
static bfs::path GenerateTempFile(const std::string& data) {
|
||||||
try {
|
try {
|
||||||
sfs::path path =
|
bfs::path path = bfs::temp_directory_path() / webcc::random_string(10);
|
||||||
sfs::temp_directory_path() / webcc::random_string(10);
|
|
||||||
|
|
||||||
std::ofstream ofs;
|
bfs::ofstream ofs;
|
||||||
ofs.open(path, std::ios::binary);
|
ofs.open(path, std::ios::binary);
|
||||||
if (ofs.fail()) {
|
if (ofs.fail()) {
|
||||||
return sfs::path{};
|
return bfs::path{};
|
||||||
}
|
}
|
||||||
|
|
||||||
ofs << data;
|
ofs << data;
|
||||||
|
|
||||||
return path;
|
return path;
|
||||||
|
|
||||||
} catch (const sfs::filesystem_error&) {
|
} catch (const bfs::filesystem_error&) {
|
||||||
return sfs::path{};
|
return bfs::path{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -356,8 +357,8 @@ TEST(ClientTest, Post_FileBody) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove the temp file.
|
// Remove the temp file.
|
||||||
std::error_code ec;
|
boost::system::error_code ec;
|
||||||
sfs::remove(path, ec);
|
bfs::remove(path, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WEBCC_ENABLE_GZIP
|
#if WEBCC_ENABLE_GZIP
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#include <filesystem>
|
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
## Dependencies
|
## Dependencies
|
||||||
|
|
||||||
* [Boost 1.66+](https://www.boost.org/) (asio, system, date_time)
|
* [Boost 1.66+](https://www.boost.org/) (asio, system, date_time, filesystem)
|
||||||
* [OpenSSL](https://www.openssl.org/) (for HTTPS, optional)
|
* [OpenSSL](https://www.openssl.org/) (for HTTPS, optional)
|
||||||
* [Zlib](https://www.zlib.net/) (for GZIP compression, optional)
|
* [Zlib](https://www.zlib.net/) (for GZIP compression, optional)
|
||||||
* [Googletest/gtest](https://github.com/google/googletest) (for automation and unit tests, optional)
|
* [Googletest/gtest](https://github.com/google/googletest) (for automation and unit tests, optional)
|
||||||
|
|||||||
+6
-23
@@ -2,8 +2,6 @@
|
|||||||
|
|
||||||
_For Ubuntu based Linux distributions._
|
_For Ubuntu based Linux distributions._
|
||||||
|
|
||||||
_NOTE: The usage of C++17 `filesystem` library requires GCC to be version 8 and above. It means that Webcc will not compile on Ubuntu LTS 18.04._
|
|
||||||
|
|
||||||
## Install Build Essential
|
## Install Build Essential
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -12,9 +10,7 @@ sudo apt install build-essential
|
|||||||
|
|
||||||
## Install CMake
|
## Install CMake
|
||||||
|
|
||||||
```
|
Please refer to https://apt.kitware.com/.
|
||||||
sudo apt install cmake
|
|
||||||
```
|
|
||||||
|
|
||||||
## Install Zlib & OpenSSL
|
## Install Zlib & OpenSSL
|
||||||
|
|
||||||
@@ -26,11 +22,11 @@ sudo apt install zlib1g-dev libssl-dev
|
|||||||
|
|
||||||
Download the `.tar.bz2` or `.tar.gz` from [here](https://www.boost.org/users/download/#live).
|
Download the `.tar.bz2` or `.tar.gz` from [here](https://www.boost.org/users/download/#live).
|
||||||
|
|
||||||
Unpack and go into the directory (suppose Boost version is 1.70):
|
Unpack and go into the directory (suppose Boost version is 1.74):
|
||||||
|
|
||||||
```
|
```
|
||||||
tar -xzf boost_1_70_0.tar.bz2
|
tar -xzf boost_1_74_0.tar.bz2
|
||||||
cd boost_1_70_0
|
cd boost_1_74_0
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `bootstrap.sh` to generate `b2`:
|
Run `bootstrap.sh` to generate `b2`:
|
||||||
@@ -44,7 +40,7 @@ You can change install prefix with `--prefix` (default is `/usr/local`, need `su
|
|||||||
Build and install:
|
Build and install:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo ./b2 --with-system --with-date_time variant=debug link=static threading=multi -j4 install
|
sudo ./b2 --with-system --with-date_time --with-filesystem variant=debug link=static threading=multi -j4 install
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
@@ -91,7 +87,7 @@ cmake -G"Unix Makefiles" \
|
|||||||
-DWEBCC_ENABLE_GZIP=1 \
|
-DWEBCC_ENABLE_GZIP=1 \
|
||||||
-DWEBCC_ENABLE_AUTOTEST=OFF \
|
-DWEBCC_ENABLE_AUTOTEST=OFF \
|
||||||
-DWEBCC_ENABLE_UNITTEST=OFF \
|
-DWEBCC_ENABLE_UNITTEST=OFF \
|
||||||
-DWEBCC_ENABLE_EXAMPLES=OFF \
|
-DWEBCC_ENABLE_EXAMPLES=ON \
|
||||||
..
|
..
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -108,16 +104,3 @@ make -j4
|
|||||||
```
|
```
|
||||||
|
|
||||||
The number after `-j` depends on how many CPU cores you have. You can just ignore `-j` option.
|
The number after `-j` depends on how many CPU cores you have. You can just ignore `-j` option.
|
||||||
|
|
||||||
Install the libraries:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
make install
|
|
||||||
```
|
|
||||||
|
|
||||||
If `WEBCC_ENABLE_AUTOTEST` was `ON`, you can run the automation test:
|
|
||||||
|
|
||||||
```
|
|
||||||
cd autotest
|
|
||||||
./webcc_autotest
|
|
||||||
```
|
|
||||||
|
|||||||
+5
-34
@@ -12,11 +12,11 @@ Download the .dmg from [here](https://cmake.org/download/). Just double click an
|
|||||||
|
|
||||||
Download the .tar.bz2 or .tar.gz from [here](https://www.boost.org/users/download/#live).
|
Download the .tar.bz2 or .tar.gz from [here](https://www.boost.org/users/download/#live).
|
||||||
|
|
||||||
Unpack and go into the directory (suppose Boost version is 1.70):
|
Unpack and go into the directory (suppose Boost version is 1.74):
|
||||||
|
|
||||||
```
|
```
|
||||||
tar -xzf boost_1_70_0.tar.bz2
|
tar -xzf boost_1_74_0.tar.bz2
|
||||||
cd boost_1_70_0
|
cd boost_1_74_0
|
||||||
```
|
```
|
||||||
|
|
||||||
Run `bootstrap.sh` to generate `b2`:
|
Run `bootstrap.sh` to generate `b2`:
|
||||||
@@ -30,7 +30,7 @@ You can change install prefix with `--prefix` option (default is `/usr/local`, n
|
|||||||
Build and install:
|
Build and install:
|
||||||
|
|
||||||
```
|
```
|
||||||
sudo ./b2 --with-system --with-date_time variant=debug link=static threading=multi -j4 install
|
sudo ./b2 --with-system --with-date_time --with-filesystem variant=debug link=static threading=multi -j4 install
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes:
|
Notes:
|
||||||
@@ -53,6 +53,7 @@ The libraries are installed to `/usr/local/lib`. E.g.,
|
|||||||
$ ls -l /usr/local/lib/libboost*
|
$ ls -l /usr/local/lib/libboost*
|
||||||
-rw-r--r-- 1 adam admin 540288 Apr 21 11:01 /usr/local/lib/libboost_date_time.a
|
-rw-r--r-- 1 adam admin 540288 Apr 21 11:01 /usr/local/lib/libboost_date_time.a
|
||||||
-rw-r--r-- 1 root admin 2976 Apr 21 11:01 /usr/local/lib/libboost_system.a
|
-rw-r--r-- 1 root admin 2976 Apr 21 11:01 /usr/local/lib/libboost_system.a
|
||||||
|
...
|
||||||
```
|
```
|
||||||
|
|
||||||
The headers are installed to `/usr/local/include/boost`.
|
The headers are installed to `/usr/local/include/boost`.
|
||||||
@@ -115,33 +116,3 @@ Open Terminal, go to the build directory, run `make`. E.g.,
|
|||||||
$ cd github/webcc_build
|
$ cd github/webcc_build
|
||||||
$ make -j4
|
$ make -j4
|
||||||
```
|
```
|
||||||
|
|
||||||
There might be some warnings, just ignore them.
|
|
||||||
|
|
||||||
Suppose you have checked `WEBCC_ENABLE_AUTOTEST` during the configuration, you can run it now.
|
|
||||||
|
|
||||||
```
|
|
||||||
$ cd autotest
|
|
||||||
$ ./webcc_autotest
|
|
||||||
[==========] Running 7 tests from 1 test case.
|
|
||||||
[----------] Global test environment set-up.
|
|
||||||
[----------] 7 tests from ClientTest
|
|
||||||
[ RUN ] ClientTest.Get_RequestFunc
|
|
||||||
[ OK ] ClientTest.Get_RequestFunc (1066 ms)
|
|
||||||
[ RUN ] ClientTest.Get_Shortcut
|
|
||||||
[ OK ] ClientTest.Get_Shortcut (1844 ms)
|
|
||||||
[ RUN ] ClientTest.Get_SSL
|
|
||||||
[ OK ] ClientTest.Get_SSL (2158 ms)
|
|
||||||
[ RUN ] ClientTest.Compression_Gzip
|
|
||||||
[ OK ] ClientTest.Compression_Gzip (913 ms)
|
|
||||||
[ RUN ] ClientTest.Compression_Deflate
|
|
||||||
[ OK ] ClientTest.Compression_Deflate (921 ms)
|
|
||||||
[ RUN ] ClientTest.KeepAlive
|
|
||||||
[ OK ] ClientTest.KeepAlive (5121 ms)
|
|
||||||
[ RUN ] ClientTest.GetImageJpeg
|
|
||||||
[ OK ] ClientTest.GetImageJpeg (1244 ms)
|
|
||||||
[----------] 7 tests from ClientTest (13267 ms total)
|
|
||||||
[----------] Global test environment tear-down
|
|
||||||
[==========] 7 tests from 1 test case ran. (13267 ms total)
|
|
||||||
[ PASSED ] 7 tests.
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ In the prompt, `cd` to the Boost root directory. Run `bootstrap.bat` to generate
|
|||||||
Run `b2.exe` to start the build:
|
Run `b2.exe` to start the build:
|
||||||
|
|
||||||
```
|
```
|
||||||
b2 --with-system --with-date_time variant=debug variant=release link=static threading=multi address-model=64 stage
|
b2 --with-system --with-date_time --with-filesystem variant=debug variant=release link=static threading=multi address-model=64 stage
|
||||||
```
|
```
|
||||||
|
|
||||||
NOTE: Given `address-model=64` `b2.exe` will not build any x86 libraries.
|
NOTE: Given `address-model=64` `b2.exe` will not build any x86 libraries.
|
||||||
|
|
||||||
As you can see, we only need to build `system` and `date_time` which are used by Asio. Asio itself is a header-only library.
|
As you can see, we only need to build `system`, `date_time` and `filesystem`. Asio itself is a header-only library.
|
||||||
|
|
||||||
We don't install Boost to any other place (e.g., `C:\Boost`). We just `stage` it where it is.
|
We don't install Boost to any other place (e.g., `C:\Boost`). We just `stage` it where it is.
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,16 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
#include "webcc/string.h"
|
#include "webcc/string.h"
|
||||||
|
|
||||||
#include "book_json.h"
|
#include "book_json.h"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
BookClient::BookClient(const std::string& url, int timeout)
|
BookClient::BookClient(const std::string& url, int timeout)
|
||||||
: url_(url), session_(timeout) {
|
: url_(url), session_(timeout) {
|
||||||
// Default Content-Type for requests with a body.
|
// Default Content-Type for requests with a body.
|
||||||
@@ -124,8 +128,7 @@ bool BookClient::Delete(const std::string& id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BookClient::GetPhoto(const std::string& id,
|
bool BookClient::GetPhoto(const std::string& id, const bfs::path& path) {
|
||||||
const std::filesystem::path& path) {
|
|
||||||
try {
|
try {
|
||||||
auto r = session_.Send(WEBCC_GET(url_).
|
auto r = session_.Send(WEBCC_GET(url_).
|
||||||
Path("books").Path(id).Path("photo")(),
|
Path("books").Path(id).Path("photo")(),
|
||||||
@@ -145,8 +148,7 @@ bool BookClient::GetPhoto(const std::string& id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BookClient::SetPhoto(const std::string& id,
|
bool BookClient::SetPhoto(const std::string& id, const bfs::path& path) {
|
||||||
const std::filesystem::path& path) {
|
|
||||||
try {
|
try {
|
||||||
if (!CheckPhoto(path)) {
|
if (!CheckPhoto(path)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -168,13 +170,12 @@ bool BookClient::SetPhoto(const std::string& id,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BookClient::CheckPhoto(const std::filesystem::path& photo) {
|
bool BookClient::CheckPhoto(const bfs::path& photo) {
|
||||||
if (photo.empty()) {
|
if (photo.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::is_regular_file(photo) ||
|
if (!bfs::is_regular_file(photo) || !bfs::exists(photo)) {
|
||||||
!std::filesystem::exists(photo)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#ifndef BOOK_CLIENT_H_
|
#ifndef BOOK_CLIENT_H_
|
||||||
#define BOOK_CLIENT_H_
|
#define BOOK_CLIENT_H_
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "json/json-forwards.h"
|
#include "json/json-forwards.h"
|
||||||
|
|
||||||
#include "webcc/client_session.h"
|
#include "webcc/client_session.h"
|
||||||
@@ -28,13 +29,13 @@ public:
|
|||||||
bool Delete(const std::string& id);
|
bool Delete(const std::string& id);
|
||||||
|
|
||||||
// Get photo, save to the given path.
|
// Get photo, save to the given path.
|
||||||
bool GetPhoto(const std::string& id, const std::filesystem::path& path);
|
bool GetPhoto(const std::string& id, const boost::filesystem::path& path);
|
||||||
|
|
||||||
// Set photo using the file of the given path.
|
// Set photo using the file of the given path.
|
||||||
bool SetPhoto(const std::string& id, const std::filesystem::path& path);
|
bool SetPhoto(const std::string& id, const boost::filesystem::path& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool CheckPhoto(const std::filesystem::path& photo);
|
bool CheckPhoto(const boost::filesystem::path& photo);
|
||||||
|
|
||||||
// Check HTTP response status.
|
// Check HTTP response status.
|
||||||
bool CheckStatus(webcc::ResponsePtr response, int expected_status);
|
bool CheckStatus(webcc::ResponsePtr response, int expected_status);
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
#include "book_client.h"
|
#include "book_client.h"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
void PrintSeparator() {
|
void PrintSeparator() {
|
||||||
@@ -36,9 +39,8 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
std::string url = argv[1];
|
std::string url = argv[1];
|
||||||
|
|
||||||
std::filesystem::path photo_dir = argv[2];
|
bfs::path photo_dir = argv[2];
|
||||||
if (!std::filesystem::is_directory(photo_dir) ||
|
if (!bfs::is_directory(photo_dir) || !bfs::exists(photo_dir)) {
|
||||||
!std::filesystem::exists(photo_dir)) {
|
|
||||||
std::cerr << "Invalid photo dir!" << std::endl;
|
std::cerr << "Invalid photo dir!" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
#include "webcc/server.h"
|
#include "webcc/server.h"
|
||||||
|
|
||||||
#include "views.h"
|
#include "views.h"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
std::cout << "usage: book_server <port> <upload_dir>" << std::endl;
|
std::cout << "usage: book_server <port> <upload_dir>" << std::endl;
|
||||||
@@ -18,17 +21,16 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
std::uint16_t port = static_cast<std::uint16_t>(std::atoi(argv[1]));
|
std::uint16_t port = static_cast<std::uint16_t>(std::atoi(argv[1]));
|
||||||
|
|
||||||
std::filesystem::path upload_dir = argv[2];
|
bfs::path upload_dir = argv[2];
|
||||||
if (!std::filesystem::is_directory(upload_dir) ||
|
if (!bfs::is_directory(upload_dir) || !bfs::exists(upload_dir)) {
|
||||||
!std::filesystem::exists(upload_dir)) {
|
|
||||||
std::cerr << "Invalid upload dir!" << std::endl;
|
std::cerr << "Invalid upload dir!" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a sub-dir for book photos.
|
// Add a sub-dir for book photos.
|
||||||
std::filesystem::path photo_dir = upload_dir / "books";
|
bfs::path photo_dir = upload_dir / "books";
|
||||||
if (!std::filesystem::exists(photo_dir)) {
|
if (!bfs::exists(photo_dir)) {
|
||||||
std::filesystem::create_directory(photo_dir);
|
bfs::create_directory(photo_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Book photos will be saved to: " << photo_dir << std::endl;
|
std::cout << "Book photos will be saved to: " << photo_dir << std::endl;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#include "views.h"
|
#include "views.h"
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
|
||||||
#include "webcc/response_builder.h"
|
#include "webcc/response_builder.h"
|
||||||
@@ -8,6 +10,8 @@
|
|||||||
#include "book_db.h"
|
#include "book_db.h"
|
||||||
#include "book_json.h"
|
#include "book_json.h"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
static BookDB g_book_db;
|
static BookDB g_book_db;
|
||||||
@@ -53,7 +57,7 @@ webcc::ResponsePtr BookListView::Post(webcc::RequestPtr request) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
BookDetailView::BookDetailView(std::filesystem::path photo_dir)
|
BookDetailView::BookDetailView(bfs::path photo_dir)
|
||||||
: photo_dir_(std::move(photo_dir)) {
|
: photo_dir_(std::move(photo_dir)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,8 +125,8 @@ webcc::ResponsePtr BookDetailView::Delete(webcc::RequestPtr request) {
|
|||||||
|
|
||||||
// Delete the photo from file system.
|
// Delete the photo from file system.
|
||||||
if (!photo_name.empty()) {
|
if (!photo_name.empty()) {
|
||||||
std::error_code ec;
|
boost::system::error_code ec;
|
||||||
std::filesystem::remove(photo_dir_ / photo_name, ec);
|
bfs::remove(photo_dir_ / photo_name, ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
return webcc::ResponseBuilder{}.OK()();
|
return webcc::ResponseBuilder{}.OK()();
|
||||||
@@ -130,7 +134,7 @@ webcc::ResponsePtr BookDetailView::Delete(webcc::RequestPtr request) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
BookPhotoView::BookPhotoView(std::filesystem::path photo_dir)
|
BookPhotoView::BookPhotoView(bfs::path photo_dir)
|
||||||
: photo_dir_(std::move(photo_dir)) {
|
: photo_dir_(std::move(photo_dir)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,8 +164,8 @@ webcc::ResponsePtr BookPhotoView::Get(webcc::RequestPtr request) {
|
|||||||
return webcc::ResponseBuilder{}.NotFound()();
|
return webcc::ResponseBuilder{}.NotFound()();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path photo_path = photo_dir_ / book.photo;
|
bfs::path photo_path = photo_dir_ / book.photo;
|
||||||
if (!std::filesystem::exists(photo_path)) {
|
if (!bfs::exists(photo_path)) {
|
||||||
return webcc::ResponseBuilder{}.NotFound()();
|
return webcc::ResponseBuilder{}.NotFound()();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,8 +219,8 @@ webcc::ResponsePtr BookPhotoView::Delete(webcc::RequestPtr request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Error handling is simplified.
|
// Error handling is simplified.
|
||||||
std::error_code ec;
|
boost::system::error_code ec;
|
||||||
std::filesystem::remove(photo_dir_ / book.photo, ec);
|
bfs::remove(photo_dir_ / book.photo, ec);
|
||||||
|
|
||||||
return webcc::ResponseBuilder{}.OK()();
|
return webcc::ResponseBuilder{}.OK()();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef VIEWS_H_
|
#ifndef VIEWS_H_
|
||||||
#define VIEWS_H_
|
#define VIEWS_H_
|
||||||
|
|
||||||
#include <filesystem>
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/view.h"
|
#include "webcc/view.h"
|
||||||
|
|
||||||
@@ -25,7 +25,7 @@ private:
|
|||||||
// URL: /books/{id}
|
// URL: /books/{id}
|
||||||
class BookDetailView : public webcc::View {
|
class BookDetailView : public webcc::View {
|
||||||
public:
|
public:
|
||||||
explicit BookDetailView(std::filesystem::path photo_dir);
|
explicit BookDetailView(boost::filesystem::path photo_dir);
|
||||||
|
|
||||||
webcc::ResponsePtr Handle(webcc::RequestPtr request) override;
|
webcc::ResponsePtr Handle(webcc::RequestPtr request) override;
|
||||||
|
|
||||||
@@ -40,7 +40,7 @@ private:
|
|||||||
webcc::ResponsePtr Delete(webcc::RequestPtr request);
|
webcc::ResponsePtr Delete(webcc::RequestPtr request);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path photo_dir_;
|
boost::filesystem::path photo_dir_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -48,7 +48,7 @@ private:
|
|||||||
// URL: /books/{id}/photo
|
// URL: /books/{id}/photo
|
||||||
class BookPhotoView : public webcc::View {
|
class BookPhotoView : public webcc::View {
|
||||||
public:
|
public:
|
||||||
explicit BookPhotoView(std::filesystem::path photo_dir);
|
explicit BookPhotoView(boost::filesystem::path photo_dir);
|
||||||
|
|
||||||
webcc::ResponsePtr Handle(webcc::RequestPtr request) override;
|
webcc::ResponsePtr Handle(webcc::RequestPtr request) override;
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ private:
|
|||||||
webcc::ResponsePtr Delete(webcc::RequestPtr request);
|
webcc::ResponsePtr Delete(webcc::RequestPtr request);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path photo_dir_;
|
boost::filesystem::path photo_dir_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // VIEWS_H_
|
#endif // VIEWS_H_
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
// A client posting multipart form data.
|
// A client posting multipart form data.
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "webcc/client_session.h"
|
#include "webcc/client_session.h"
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
|
|
||||||
namespace sfs = std::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc < 2) {
|
if (argc < 2) {
|
||||||
@@ -23,7 +24,7 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
WEBCC_LOG_INIT("", webcc::LOG_CONSOLE);
|
||||||
|
|
||||||
const sfs::path upload_dir(argv[1]);
|
const bfs::path upload_dir(argv[1]);
|
||||||
|
|
||||||
std::string url;
|
std::string url;
|
||||||
if (argc == 3) {
|
if (argc == 3) {
|
||||||
@@ -32,7 +33,7 @@ int main(int argc, char* argv[]) {
|
|||||||
url = "http://httpbin.org/post";
|
url = "http://httpbin.org/post";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sfs::is_directory(upload_dir) || !sfs::exists(upload_dir)) {
|
if (!bfs::is_directory(upload_dir) || !bfs::exists(upload_dir)) {
|
||||||
std::cerr << "Invalid upload dir!" << std::endl;
|
std::cerr << "Invalid upload dir!" << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-7
@@ -1,5 +1,7 @@
|
|||||||
#include "webcc/body.h"
|
#include "webcc/body.h"
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
#include "webcc/utility.h"
|
#include "webcc/utility.h"
|
||||||
|
|
||||||
@@ -7,6 +9,8 @@
|
|||||||
#include "webcc/gzip.h"
|
#include "webcc/gzip.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -153,7 +157,7 @@ void FormBody::Free(std::size_t index) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
FileBody::FileBody(const std::filesystem::path& path, std::size_t chunk_size)
|
FileBody::FileBody(const bfs::path& path, std::size_t chunk_size)
|
||||||
: path_(path), chunk_size_(chunk_size), auto_delete_(false), size_(0) {
|
: path_(path), chunk_size_(chunk_size), auto_delete_(false), size_(0) {
|
||||||
size_ = utility::TellSize(path_);
|
size_ = utility::TellSize(path_);
|
||||||
if (size_ == kInvalidLength) {
|
if (size_ == kInvalidLength) {
|
||||||
@@ -161,15 +165,15 @@ FileBody::FileBody(const std::filesystem::path& path, std::size_t chunk_size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FileBody::FileBody(const std::filesystem::path& path, bool auto_delete)
|
FileBody::FileBody(const bfs::path& path, bool auto_delete)
|
||||||
: path_(path), chunk_size_(0), auto_delete_(auto_delete), size_(0) {
|
: path_(path), chunk_size_(0), auto_delete_(auto_delete), size_(0) {
|
||||||
// Don't need to tell file size.
|
// Don't need to tell file size.
|
||||||
}
|
}
|
||||||
|
|
||||||
FileBody::~FileBody() {
|
FileBody::~FileBody() {
|
||||||
if (auto_delete_ && !path_.empty()) {
|
if (auto_delete_ && !path_.empty()) {
|
||||||
std::error_code ec;
|
boost::system::error_code ec;
|
||||||
std::filesystem::remove(path_, ec);
|
bfs::remove(path_, ec);
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Failed to remove file (%s).", ec.message().c_str());
|
LOG_ERRO("Failed to remove file (%s).", ec.message().c_str());
|
||||||
}
|
}
|
||||||
@@ -205,7 +209,7 @@ void FileBody::Dump(std::ostream& os, const std::string& prefix) const {
|
|||||||
os << prefix << "<file: " << path_.string() << ">" << std::endl;
|
os << prefix << "<file: " << path_.string() << ">" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileBody::Move(const std::filesystem::path& new_path) {
|
bool FileBody::Move(const bfs::path& new_path) {
|
||||||
if (path_ == new_path) {
|
if (path_ == new_path) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -214,8 +218,8 @@ bool FileBody::Move(const std::filesystem::path& new_path) {
|
|||||||
ifstream_.close();
|
ifstream_.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::error_code ec;
|
boost::system::error_code ec;
|
||||||
std::filesystem::rename(path_, new_path, ec);
|
bfs::rename(path_, new_path, ec);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERRO("Failed to rename file (%s).", ec.message().c_str());
|
LOG_ERRO("Failed to rename file (%s).", ec.message().c_str());
|
||||||
|
|||||||
+10
-8
@@ -1,12 +1,14 @@
|
|||||||
#ifndef WEBCC_BODY_H_
|
#ifndef WEBCC_BODY_H_
|
||||||
#define WEBCC_BODY_H_
|
#define WEBCC_BODY_H_
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "boost/filesystem/fstream.hpp"
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/common.h"
|
#include "webcc/common.h"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
@@ -152,14 +154,14 @@ private:
|
|||||||
class FileBody : public Body {
|
class FileBody : public Body {
|
||||||
public:
|
public:
|
||||||
// For message to be sent out.
|
// For message to be sent out.
|
||||||
FileBody(const std::filesystem::path& path, std::size_t chunk_size);
|
FileBody(const boost::filesystem::path& path, std::size_t chunk_size);
|
||||||
|
|
||||||
// For message received.
|
// For message received.
|
||||||
// No |chunk_size| is needed since you don't iterate the payload of a
|
// No |chunk_size| is needed since you don't iterate the payload of a
|
||||||
// received message.
|
// received message.
|
||||||
// If |auto_delete| is true, the file will be deleted on destructor unless it
|
// If |auto_delete| is true, the file will be deleted on destructor unless it
|
||||||
// is moved to another path (see Move()).
|
// is moved to another path (see Move()).
|
||||||
FileBody(const std::filesystem::path& path, bool auto_delete = false);
|
FileBody(const boost::filesystem::path& path, bool auto_delete = false);
|
||||||
|
|
||||||
~FileBody() override;
|
~FileBody() override;
|
||||||
|
|
||||||
@@ -173,7 +175,7 @@ public:
|
|||||||
|
|
||||||
void Dump(std::ostream& os, const std::string& prefix) const override;
|
void Dump(std::ostream& os, const std::string& prefix) const override;
|
||||||
|
|
||||||
const std::filesystem::path& path() const {
|
const boost::filesystem::path& path() const {
|
||||||
return path_;
|
return path_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -186,17 +188,17 @@ public:
|
|||||||
// If |new_path| resolves to an existing non-directory file, it is removed.
|
// If |new_path| resolves to an existing non-directory file, it is removed.
|
||||||
// If |new_path| resolves to an existing directory, it is removed if empty
|
// If |new_path| resolves to an existing directory, it is removed if empty
|
||||||
// on ISO/IEC 9945 but is an error on Windows.
|
// on ISO/IEC 9945 but is an error on Windows.
|
||||||
// See std::filesystem::rename() for more details.
|
// See boost::filesystem::rename() for more details.
|
||||||
bool Move(const std::filesystem::path& new_path);
|
bool Move(const boost::filesystem::path& new_path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::filesystem::path path_;
|
boost::filesystem::path path_;
|
||||||
std::size_t chunk_size_;
|
std::size_t chunk_size_;
|
||||||
bool auto_delete_;
|
bool auto_delete_;
|
||||||
|
|
||||||
std::size_t size_; // File size in bytes
|
std::size_t size_; // File size in bytes
|
||||||
|
|
||||||
std::ifstream ifstream_;
|
boost::filesystem::ifstream ifstream_;
|
||||||
std::string chunk_;
|
std::string chunk_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -6,6 +6,8 @@
|
|||||||
#include "webcc/string.h"
|
#include "webcc/string.h"
|
||||||
#include "webcc/utility.h"
|
#include "webcc/utility.h"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -190,8 +192,7 @@ FormPartPtr FormPart::New(const std::string& name, std::string&& data,
|
|||||||
return form_part;
|
return form_part;
|
||||||
}
|
}
|
||||||
|
|
||||||
FormPartPtr FormPart::NewFile(const std::string& name,
|
FormPartPtr FormPart::NewFile(const std::string& name, const bfs::path& path,
|
||||||
const std::filesystem::path& path,
|
|
||||||
const std::string& media_type) {
|
const std::string& media_type) {
|
||||||
auto form_part = std::make_shared<FormPart>();
|
auto form_part = std::make_shared<FormPart>();
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -2,11 +2,12 @@
|
|||||||
#define WEBCC_COMMON_H_
|
#define WEBCC_COMMON_H_
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/globals.h"
|
#include "webcc/globals.h"
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
@@ -158,7 +159,7 @@ public:
|
|||||||
// The file name will be extracted from path.
|
// The file name will be extracted from path.
|
||||||
// The media type, if not provided, will be inferred from file extension.
|
// The media type, if not provided, will be inferred from file extension.
|
||||||
static FormPartPtr NewFile(const std::string& name,
|
static FormPartPtr NewFile(const std::string& name,
|
||||||
const std::filesystem::path& path,
|
const boost::filesystem::path& path,
|
||||||
const std::string& media_type = "");
|
const std::string& media_type = "");
|
||||||
|
|
||||||
// API: SERVER
|
// API: SERVER
|
||||||
@@ -229,7 +230,7 @@ private:
|
|||||||
std::string name_;
|
std::string name_;
|
||||||
|
|
||||||
// The path of the file to post.
|
// The path of the file to post.
|
||||||
std::filesystem::path path_;
|
boost::filesystem::path path_;
|
||||||
|
|
||||||
// The original local file name.
|
// The original local file name.
|
||||||
// E.g., "baby.jpg".
|
// E.g., "baby.jpg".
|
||||||
|
|||||||
+13
-10
@@ -6,7 +6,6 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdarg>
|
#include <cstdarg>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <filesystem>
|
|
||||||
#include <iomanip> // for put_time
|
#include <iomanip> // for put_time
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -21,6 +20,10 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -33,7 +36,7 @@ static const char* kLevelNames[] = {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
static FILE* FOpen(const std::filesystem::path& path, bool overwrite) {
|
static FILE* FOpen(const bfs::path& path, bool overwrite) {
|
||||||
#if (defined(_WIN32) || defined(_WIN64))
|
#if (defined(_WIN32) || defined(_WIN64))
|
||||||
return _wfopen(path.wstring().c_str(), overwrite ? L"w+" : L"a+");
|
return _wfopen(path.wstring().c_str(), overwrite ? L"w+" : L"a+");
|
||||||
#else
|
#else
|
||||||
@@ -45,7 +48,7 @@ struct Logger {
|
|||||||
Logger() : file(nullptr), modes(0) {
|
Logger() : file(nullptr), modes(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init(const std::filesystem::path& path, int _modes) {
|
void Init(const bfs::path& path, int _modes) {
|
||||||
modes = _modes;
|
modes = _modes;
|
||||||
|
|
||||||
// Create log file only if necessary.
|
// Create log file only if necessary.
|
||||||
@@ -153,22 +156,22 @@ static std::string GetThreadID() {
|
|||||||
return thread_id;
|
return thread_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::filesystem::path InitLogPath(const std::filesystem::path& dir) {
|
static bfs::path InitLogPath(const bfs::path& dir) {
|
||||||
if (dir.empty()) {
|
if (dir.empty()) {
|
||||||
return std::filesystem::current_path() / WEBCC_LOG_FILE_NAME;
|
return bfs::current_path() / WEBCC_LOG_FILE_NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!std::filesystem::exists(dir) || !std::filesystem::is_directory(dir)) {
|
if (!bfs::exists(dir) || !bfs::is_directory(dir)) {
|
||||||
std::error_code ec;
|
boost::system::error_code ec;
|
||||||
if (!std::filesystem::create_directories(dir, ec) || ec) {
|
if (!bfs::create_directories(dir, ec) || ec) {
|
||||||
return std::filesystem::path{};
|
return bfs::path{};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (dir / WEBCC_LOG_FILE_NAME);
|
return (dir / WEBCC_LOG_FILE_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LogInit(const std::filesystem::path& dir, int modes) {
|
void LogInit(const bfs::path& dir, int modes) {
|
||||||
// Suppose this is called from the main thread.
|
// Suppose this is called from the main thread.
|
||||||
g_main_thread_id = DoGetThreadID();
|
g_main_thread_id = DoGetThreadID();
|
||||||
|
|
||||||
|
|||||||
+2
-7
@@ -9,12 +9,7 @@
|
|||||||
#include <cstring> // for strrchr()
|
#include <cstring> // for strrchr()
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Avoid include <filesystem> in the header.
|
#include "boost/filesystem/path.hpp"
|
||||||
namespace std {
|
|
||||||
namespace filesystem {
|
|
||||||
class path;
|
|
||||||
} // namespace filesystem
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
// Log levels.
|
// Log levels.
|
||||||
// VERB is similar to DEBUG commonly used by other projects.
|
// VERB is similar to DEBUG commonly used by other projects.
|
||||||
@@ -49,7 +44,7 @@ const int LOG_FILE_OVERWRITE = LOG_FILE | LOG_OVERWRITE;
|
|||||||
|
|
||||||
// Initialize logger.
|
// Initialize logger.
|
||||||
// If |dir| is empty, log file will be generated in current directory.
|
// If |dir| is empty, log file will be generated in current directory.
|
||||||
void LogInit(const std::filesystem::path& dir, int modes);
|
void LogInit(const boost::filesystem::path& dir, int modes);
|
||||||
|
|
||||||
void Log(int level, const char* file, int line, const char* format, ...);
|
void Log(int level, const char* file, int line, const char* format, ...);
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -1,5 +1,7 @@
|
|||||||
#include "webcc/parser.h"
|
#include "webcc/parser.h"
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
#include "webcc/message.h"
|
#include "webcc/message.h"
|
||||||
#include "webcc/string.h"
|
#include "webcc/string.h"
|
||||||
@@ -9,6 +11,8 @@
|
|||||||
#include "webcc/gzip.h"
|
#include "webcc/gzip.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
@@ -65,7 +69,7 @@ bool StringBodyHandler::Finish() {
|
|||||||
|
|
||||||
bool FileBodyHandler::OpenFile() {
|
bool FileBodyHandler::OpenFile() {
|
||||||
try {
|
try {
|
||||||
temp_path_ = std::filesystem::temp_directory_path();
|
temp_path_ = bfs::temp_directory_path();
|
||||||
|
|
||||||
// Generate a random string as file name.
|
// Generate a random string as file name.
|
||||||
// A replacement of boost::filesystem::unique_path().
|
// A replacement of boost::filesystem::unique_path().
|
||||||
@@ -74,7 +78,7 @@ bool FileBodyHandler::OpenFile() {
|
|||||||
LOG_VERB("Generate a temp path for streaming: %s",
|
LOG_VERB("Generate a temp path for streaming: %s",
|
||||||
temp_path_.string().c_str());
|
temp_path_.string().c_str());
|
||||||
|
|
||||||
} catch (const std::filesystem::filesystem_error&) {
|
} catch (const bfs::filesystem_error&) {
|
||||||
LOG_ERRO("Failed to generate temp path for streaming.");
|
LOG_ERRO("Failed to generate temp path for streaming.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-3
@@ -1,10 +1,12 @@
|
|||||||
#ifndef WEBCC_PARSER_H_
|
#ifndef WEBCC_PARSER_H_
|
||||||
#define WEBCC_PARSER_H_
|
#define WEBCC_PARSER_H_
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "boost/filesystem/fstream.hpp"
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/common.h"
|
#include "webcc/common.h"
|
||||||
#include "webcc/globals.h"
|
#include "webcc/globals.h"
|
||||||
|
|
||||||
@@ -82,8 +84,8 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::size_t streamed_size_ = 0;
|
std::size_t streamed_size_ = 0;
|
||||||
std::ofstream ofstream_;
|
boost::filesystem::ofstream ofstream_;
|
||||||
std::filesystem::path temp_path_;
|
boost::filesystem::path temp_path_;
|
||||||
};
|
};
|
||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "webcc/gzip.h"
|
#include "webcc/gzip.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
RequestPtr RequestBuilder::operator()() {
|
RequestPtr RequestBuilder::operator()() {
|
||||||
@@ -52,7 +54,7 @@ RequestPtr RequestBuilder::operator()() {
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestBuilder& RequestBuilder::File(const std::filesystem::path& path,
|
RequestBuilder& RequestBuilder::File(const bfs::path& path,
|
||||||
bool infer_media_type,
|
bool infer_media_type,
|
||||||
std::size_t chunk_size) {
|
std::size_t chunk_size) {
|
||||||
body_.reset(new FileBody{ path, chunk_size });
|
body_.reset(new FileBody{ path, chunk_size });
|
||||||
@@ -65,7 +67,7 @@ RequestBuilder& RequestBuilder::File(const std::filesystem::path& path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
RequestBuilder& RequestBuilder::FormFile(const std::string& name,
|
RequestBuilder& RequestBuilder::FormFile(const std::string& name,
|
||||||
const std::filesystem::path& path,
|
const bfs::path& path,
|
||||||
const std::string& media_type) {
|
const std::string& media_type) {
|
||||||
assert(!name.empty());
|
assert(!name.empty());
|
||||||
return Form(FormPart::NewFile(name, path, media_type));
|
return Form(FormPart::NewFile(name, path, media_type));
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#ifndef WEBCC_REQUEST_BUILDER_H_
|
#ifndef WEBCC_REQUEST_BUILDER_H_
|
||||||
#define WEBCC_REQUEST_BUILDER_H_
|
#define WEBCC_REQUEST_BUILDER_H_
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/request.h"
|
#include "webcc/request.h"
|
||||||
#include "webcc/url.h"
|
#include "webcc/url.h"
|
||||||
|
|
||||||
@@ -135,7 +136,7 @@ public:
|
|||||||
|
|
||||||
// Use the file content as body.
|
// Use the file content as body.
|
||||||
// NOTE: Error::kFileError might be thrown.
|
// NOTE: Error::kFileError might be thrown.
|
||||||
RequestBuilder& File(const std::filesystem::path& path,
|
RequestBuilder& File(const boost::filesystem::path& path,
|
||||||
bool infer_media_type = true,
|
bool infer_media_type = true,
|
||||||
std::size_t chunk_size = 1024);
|
std::size_t chunk_size = 1024);
|
||||||
|
|
||||||
@@ -147,7 +148,7 @@ public:
|
|||||||
|
|
||||||
// Add a form part of file.
|
// Add a form part of file.
|
||||||
RequestBuilder& FormFile(const std::string& name,
|
RequestBuilder& FormFile(const std::string& name,
|
||||||
const std::filesystem::path& path,
|
const boost::filesystem::path& path,
|
||||||
const std::string& media_type = "");
|
const std::string& media_type = "");
|
||||||
|
|
||||||
// Add a form part of string data.
|
// Add a form part of string data.
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "webcc/gzip.h"
|
#include "webcc/gzip.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
ResponsePtr ResponseBuilder::operator()() {
|
ResponsePtr ResponseBuilder::operator()() {
|
||||||
@@ -43,7 +45,7 @@ ResponsePtr ResponseBuilder::operator()() {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResponseBuilder& ResponseBuilder::File(const std::filesystem::path& path,
|
ResponseBuilder& ResponseBuilder::File(const bfs::path& path,
|
||||||
bool infer_media_type,
|
bool infer_media_type,
|
||||||
std::size_t chunk_size) {
|
std::size_t chunk_size) {
|
||||||
body_.reset(new FileBody{ path, chunk_size });
|
body_.reset(new FileBody{ path, chunk_size });
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/request.h"
|
#include "webcc/request.h"
|
||||||
#include "webcc/response.h"
|
#include "webcc/response.h"
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ public:
|
|||||||
|
|
||||||
// Use the file content as body.
|
// Use the file content as body.
|
||||||
// NOTE: Error::kFileError might be thrown.
|
// NOTE: Error::kFileError might be thrown.
|
||||||
ResponseBuilder& File(const std::filesystem::path& path,
|
ResponseBuilder& File(const boost::filesystem::path& path,
|
||||||
bool infer_media_type = true,
|
bool infer_media_type = true,
|
||||||
std::size_t chunk_size = 1024);
|
std::size_t chunk_size = 1024);
|
||||||
|
|
||||||
|
|||||||
+7
-5
@@ -4,20 +4,22 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
#include "boost/filesystem/operations.hpp"
|
||||||
|
|
||||||
#include "webcc/body.h"
|
#include "webcc/body.h"
|
||||||
#include "webcc/logger.h"
|
#include "webcc/logger.h"
|
||||||
#include "webcc/request.h"
|
#include "webcc/request.h"
|
||||||
#include "webcc/response.h"
|
#include "webcc/response.h"
|
||||||
#include "webcc/utility.h"
|
#include "webcc/utility.h"
|
||||||
|
|
||||||
namespace sfs = std::filesystem;
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
using tcp = boost::asio::ip::tcp;
|
using tcp = boost::asio::ip::tcp;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
|
|
||||||
Server::Server(boost::asio::ip::tcp protocol, std::uint16_t port,
|
Server::Server(boost::asio::ip::tcp protocol, std::uint16_t port,
|
||||||
const sfs::path& doc_root)
|
const bfs::path& doc_root)
|
||||||
: protocol_(protocol),
|
: protocol_(protocol),
|
||||||
port_(port),
|
port_(port),
|
||||||
doc_root_(doc_root),
|
doc_root_(doc_root),
|
||||||
@@ -302,8 +304,8 @@ bool Server::MatchViewOrStatic(const std::string& method,
|
|||||||
|
|
||||||
// Try to match a static file.
|
// Try to match a static file.
|
||||||
if (method == methods::kGet && !doc_root_.empty()) {
|
if (method == methods::kGet && !doc_root_.empty()) {
|
||||||
sfs::path path = doc_root_ / url;
|
bfs::path path = doc_root_ / url;
|
||||||
if (!sfs::is_directory(path) && sfs::exists(path)) {
|
if (!bfs::is_directory(path) && bfs::exists(path)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -319,7 +321,7 @@ ResponsePtr Server::ServeStatic(RequestPtr request) {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
sfs::path path = doc_root_ / request->url().path();
|
bfs::path path = doc_root_ / request->url().path();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// NOTE: FileBody might throw Error::kFileError.
|
// NOTE: FileBody might throw Error::kFileError.
|
||||||
|
|||||||
+4
-3
@@ -1,11 +1,12 @@
|
|||||||
#ifndef WEBCC_SERVER_H_
|
#ifndef WEBCC_SERVER_H_
|
||||||
#define WEBCC_SERVER_H_
|
#define WEBCC_SERVER_H_
|
||||||
|
|
||||||
#include <filesystem>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "boost/asio/io_context.hpp"
|
#include "boost/asio/io_context.hpp"
|
||||||
#include "boost/asio/ip/tcp.hpp"
|
#include "boost/asio/ip/tcp.hpp"
|
||||||
#include "boost/asio/signal_set.hpp"
|
#include "boost/asio/signal_set.hpp"
|
||||||
@@ -21,7 +22,7 @@ namespace webcc {
|
|||||||
class Server : public Router {
|
class Server : public Router {
|
||||||
public:
|
public:
|
||||||
Server(boost::asio::ip::tcp protocol, std::uint16_t port,
|
Server(boost::asio::ip::tcp protocol, std::uint16_t port,
|
||||||
const std::filesystem::path& doc_root = {});
|
const boost::filesystem::path& doc_root = {});
|
||||||
|
|
||||||
~Server() = default;
|
~Server() = default;
|
||||||
|
|
||||||
@@ -101,7 +102,7 @@ private:
|
|||||||
std::uint16_t port_;
|
std::uint16_t port_;
|
||||||
|
|
||||||
// The directory with the static files to be served.
|
// The directory with the static files to be served.
|
||||||
std::filesystem::path doc_root_;
|
boost::filesystem::path doc_root_;
|
||||||
|
|
||||||
// The size of the chunk loaded into memory each time when serving a
|
// The size of the chunk loaded into memory each time when serving a
|
||||||
// static file.
|
// static file.
|
||||||
|
|||||||
+8
-5
@@ -2,15 +2,18 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <filesystem>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip> // for put_time
|
#include <iomanip> // for put_time
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "boost/filesystem/fstream.hpp"
|
||||||
|
|
||||||
#include "webcc/string.h"
|
#include "webcc/string.h"
|
||||||
#include "webcc/version.h"
|
#include "webcc/version.h"
|
||||||
|
|
||||||
|
namespace bfs = boost::filesystem;
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
namespace utility {
|
namespace utility {
|
||||||
|
|
||||||
@@ -49,18 +52,18 @@ std::string HttpDate() {
|
|||||||
return std::string(buf) + " GMT";
|
return std::string(buf) + " GMT";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t TellSize(const std::filesystem::path& path) {
|
std::size_t TellSize(const bfs::path& path) {
|
||||||
// Flag "ate": seek to the end of stream immediately after open.
|
// Flag "ate": seek to the end of stream immediately after open.
|
||||||
std::ifstream stream{ path, std::ios::binary | std::ios::ate };
|
bfs::ifstream stream{ path, std::ios::binary | std::ios::ate };
|
||||||
if (stream.fail()) {
|
if (stream.fail()) {
|
||||||
return kInvalidLength;
|
return kInvalidLength;
|
||||||
}
|
}
|
||||||
return static_cast<std::size_t>(stream.tellg());
|
return static_cast<std::size_t>(stream.tellg());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadFile(const std::filesystem::path& path, std::string* output) {
|
bool ReadFile(const bfs::path& path, std::string* output) {
|
||||||
// Flag "ate": seek to the end of stream immediately after open.
|
// Flag "ate": seek to the end of stream immediately after open.
|
||||||
std::ifstream stream{ path, std::ios::binary | std::ios::ate };
|
bfs::ifstream stream{ path, std::ios::binary | std::ios::ate };
|
||||||
if (stream.fail()) {
|
if (stream.fail()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-9
@@ -5,16 +5,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "boost/asio/ip/tcp.hpp"
|
#include "boost/asio/ip/tcp.hpp"
|
||||||
|
#include "boost/filesystem/path.hpp"
|
||||||
|
|
||||||
#include "webcc/globals.h"
|
#include "webcc/globals.h"
|
||||||
|
|
||||||
// Avoid include <filesystem> in the header.
|
|
||||||
namespace std {
|
|
||||||
namespace filesystem {
|
|
||||||
class path;
|
|
||||||
} // namespace filesystem
|
|
||||||
} // namespace std
|
|
||||||
|
|
||||||
namespace webcc {
|
namespace webcc {
|
||||||
namespace utility {
|
namespace utility {
|
||||||
|
|
||||||
@@ -28,10 +22,10 @@ std::string HttpDate();
|
|||||||
|
|
||||||
// Tell the size in bytes of the given file.
|
// Tell the size in bytes of the given file.
|
||||||
// Return kInvalidLength (-1) on failure.
|
// Return kInvalidLength (-1) on failure.
|
||||||
std::size_t TellSize(const std::filesystem::path& path);
|
std::size_t TellSize(const boost::filesystem::path& path);
|
||||||
|
|
||||||
// Read entire file into string.
|
// Read entire file into string.
|
||||||
bool ReadFile(const std::filesystem::path& path, std::string* output);
|
bool ReadFile(const boost::filesystem::path& path, std::string* output);
|
||||||
|
|
||||||
// Dump the string data line by line to achieve more readability.
|
// Dump the string data line by line to achieve more readability.
|
||||||
// Also limit the maximum size of the data to be dumped.
|
// Also limit the maximum size of the data to be dumped.
|
||||||
|
|||||||
Reference in New Issue
Block a user