Giter Site home page Giter Site logo

mattgodbolt / seasocks Goto Github PK

View Code? Open in Web Editor NEW
716.0 38.0 119.0 1.44 MB

Simple, small, C++ embeddable webserver with WebSockets support

License: BSD 2-Clause "Simplified" License

Shell 0.07% Python 0.53% C++ 87.97% C 9.96% Makefile 0.07% CSS 0.07% HTML 0.25% JavaScript 0.18% CMake 0.90%
websocket-server c-plus-plus websockets cpp14

seasocks's Introduction

Seasocks - A tiny embeddable C++ HTTP and WebSocket server

CI codecov GitHub release License ConanCenter package

Features

  • Simple C++ API
  • Serves static content from disk
  • API for building WebSocket servers
  • Simple command line binary for quick serving of static files only
  • Supports newer Hybi-10 and Hybi-16 WebSockets as well as the older Hixie style.
  • Supports Linux and Windows

Stuff it doesn't do

  • It's not nearly as configurable as Apache, Lighttpd, Nginx, Jetty, etc.
  • It provides only limited support for custom content generation (e.g. Servlets).
  • It has been designed for WebSocket based control.
  • It probably won't work on other systems (patches to support other systems would be welcome, but not a priority for us)

Getting started

Check out the tutorial on the wiki.

See src/app/c/ws_test.cpp for an example.

seasocks's People

Contributors

0xcaff avatar austinschuh avatar chausner avatar dhouck avatar eriklee avatar hoytech avatar iwanders avatar jasper-ben avatar joewalnes avatar madebr avatar mattgodbolt avatar membar avatar nkowdley avatar offa avatar peterbindels-tomtom avatar rayburgemeestre avatar seeekr avatar shin-nn avatar sjk7 avatar twanas avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

seasocks's Issues

Moving statistics to separate Handler

Wouldn't be better and cleaner solution to move statistis to separate Handler? Than it would be more secure to use server without possibility of leaking info out.

seasocks error with chromium/chrome

Hello,
I like your websocket-implementation because of its simplicity and purity. Sadly I obtain an error when I try to log in with chrome on android or chromium on linux, an error which is not present under firefox: "Error during WebSocket handshake: Sent non-empty 'Sec-WebSocket-Protocol' header but no response was received."
Do you know this problem?
Greetings
Marc

The example code doesn't work in chrome

"See src/app/c/ws_test.cpp for an example"

The example code doesn't work in Chrome(43.0.2357.132 m), but works in IE11 and Firefox 39.0.

The digital number doesn't change at all in Chrome no matter how you click it.

Is there any special issue for Chrome? Or something wrong in the app.js?

findEmbeddedContent symbol missing

After installing the latest version of seasocks, I'm having trouble building against libseasocks.a:

/usr/local/lib/libseasocks.a(Connection.cpp.o): In function `seasocks::Connection::sendError(seasocks::ResponseCode, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
Connection.cpp:(.text+0x4c2c): undefined reference to `findEmbeddedContent(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/local/lib/libseasocks.a(Connection.cpp.o): In function `seasocks::Connection::send404()':
Connection.cpp:(.text+0x52b5): undefined reference to `findEmbeddedContent(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/local/lib/libseasocks.a(Connection.cpp.o): In function `seasocks::Connection::processHeaders(unsigned char*, unsigned char*)':
Connection.cpp:(.text+0x6424): undefined reference to `findEmbeddedContent(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status

ToStringTests fails

I have a test failure of ToStringTests with following error (Gcc 6):

[…]/seasocks/src/test/c/ToStringTests.cpp:32: FAILED:
  {Unknown expression after the reported line}
due to unexpected exception with message:
  locale::facet::_S_create_c_locale name not valid

===============================================================================
test cases:    45 |    44 passed | 1 failed
assertions: 65939 | 65938 passed | 1 failed

According to this, the locale name strings are implementation specific.

Some code related questions

I have some code related questions:

  1. Is the -ggdb3 flag still necessary? It's enabled for all build types; but mainly debug related (correct?).
  2. Are the compiler checks for map::emplace() and override still necessary? Any C++11 conform compiler should support thesei).

i) The test for <atomic> isn't affected by this, as it still serves a valid reason – eg. some embedded systems may not support it.

Error During compilation

Hello
the compilcation fail for me ( all warnings being treated as errors) on the latest update :
11%] Building CXX object src/main/c/CMakeFiles/seasocks.dir/Connection.cpp.o
Connection.cpp:
In member function ‘void seasocks::Connection::writeChunkHeader(size_t)’:

Connection.cpp:934:65: erreur: format ‘%lx’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘size_t {aka unsigned int}’ [-Werror=format=]
_chunk ? "\r\n%lx\r\n" : "%lx\r\n", size);

regards,
david

Support automatically cascading PathHandlers

In order to host a CrackedUriPageHandler on a path like /foo/bar/baz, it seems to me that a separate PathHandler handler has to be created for each component of the path with the CrackedUriPageHandler only set up on the last part of the address.

If my handler class is DataHandler, it seems I have to do something like this to add it at the address /foo/bar/baz

auto root = make_shared<RootPageHandler>();
auto fooHandler = make_shared<PathHandler>("foo");
auto barHandler = make_shared<PathHandler>("bar");
auto bazHandler = make_shared<PathHandler>("baz", make_shared<DataHandler>());
root->add(fooHandler);

Is there any way to avoid having to make all of the intermediate path parts and so something like this?

auto root = make_shared<RootPageHandler>();
auto pageHandler = make_shared<AutoCrackedPathHandler>("/foo/bar/baz", make_shared<DataHandler>());
root->add(pageHandler);

Benchmark

Do you have any benchmark on how this lib performs?

Switching to C++14?

What about switching to C++14 (eg. in form the of seasocks v1.4)?

C++14 is now widely adopted and supported. Furthermore, GCC uses it as default since GCC6 and Clang will also do so from Clang6 onwards. Pretty much every OS should have at least GCC5 (respectively capable Clang) somehow available too.


Todo

  • Enable C++14 on master
  • Tag and release current HEAD as v1.3.2
  • Add a note, that v1.4.x will require C++14
  • Review supported compiler

seasocks::Server as both REST-server and WebSocket-server on single port runtime?

Can I run seasocks::Server as both REST-server and WebSocket-server on single port?
I want to make my server with REST-API and WebSockets API both in runtime.
Sample of my code:

seasocks::Server server(logger);
 auto restHandler = std::make_shared<MyRESTHandler>();
 server.addPageHandler(restHandler);
 auto wsHandler = std::make_shared<MyWSHandler>(&server);
 server.addWebSocketHandler("/path?ws", wsHandler);
 if(!server.startListening(my_port)) return EXIT_FAILURE;
 server.loop();

But requests like 'http://localhost:my_port/path' and 'ws://localhost:my_port/path?ws' routes into restHandler only. WebSocket-requests cannot routes to wsHandler =(
I don't understand the gist of seasocks kernel. Help me, please!

Multi-thread request

I run the ws_test example and use java as the client, when I use multi thread to request the response comes one by one, it looks like the server can not handle multi thread request at the same time.

Running gen_embedded.py fails with python 3

Building seasocks with fails if Python defaults to Python 3 (i'm using 3.4.3):

Running make

...
scripts/gen_embedded.py src/main/web/favicon.ico src/main/web/_404.png src/main/web/_error.html src/main/web/_stats.html src/main/web/_jquery.min.js src/main/web/_error.css src/main/web/_seasocks.css | g++ -g -O2 -std=c++11 -pthread -fPIC -Wall -Werror '-DSEASOCKS_VERSION_STRING="SeaSocks/unversioned (57c572f)"' -Isrc/main/c -x c++ -c -o "obj/embedded.o" -
  File "scripts/gen_embedded.py", line 14
    """
      ^
SyntaxError: Missing parentheses in call to 'print'
...

Build steps:

autoconf
./configure
make

Since make executes the script, building fails.

Running gen_embedded.py manually:

./gen_embedded.py 
  File "./gen_embedded.py", line 14
    """
      ^
SyntaxError: Missing parentheses in call to 'print'

Workarounds

  1. Running the script manually using pyhton2 gen_embedded.py
  2. Changing #!/usr/bin/env python to #!/usr/bin/env python2 in the script

issues of seasocks' dependency on libz

This might or might not related to seasocks, because I can build seasocks source w/o problem. Only when I built another program that depends on seasocks I got this:

/usr/bin/ld: /usr/lib/gcc/x86_64-linux-gnu/7/../../../x86_64-linux-gnu/libseasocks.a(ZlibContext.cpp.o): undefined reference to symbol 'inflateEnd'
//lib/x86_64-linux-gnu/libz.so.1: error adding symbols: DSO missing from command line

from my earlier note it seemed that an earlier version of seasocks could bypass this issue.

my libz is libz.so.1.2.11

any ideas?

error: 'clientBufferSize' on compilation

/Users/dendisuhubdy/dev/seasocks/src/main/c/./seasocks/Server.h:120:12: error: 'clientBufferSize' overrides a member function but is not marked 'override' [-Werror,-Winconsistent-missing-override]
    size_t clientBufferSize() const { return _clientBufferSize; }
           ^
/Users/dendisuhubdy/dev/seasocks/src/main/c/./seasocks/ServerImpl.h:54:20: note: overridden virtual function is here
    virtual size_t clientBufferSize() const = 0;
                   ^
/Users/dendisuhubdy/dev/seasocks/src/main/c/Connection.cpp:301:47: error: use of undeclared identifier 'MSG_NOSIGNAL'
    auto sendResult = ::send(_fd, data, size, MSG_NOSIGNAL);
                                              ^
/Users/dendisuhubdy/dev/seasocks/src/main/c/Connection.cpp:584:32: error: use of undeclared identifier '__bswap_64'
        uint64_t lengthBytes = __bswap_64(messageLength);

Response getting corrupt - question

I have written the following code (reduced and modified to the essential parts for posting here) to implement a response to a uri path "show". I want to generate a response in the code and return it. I generated this response in many different ways, but the result is always the following error.

When I return a response string of length >=1000, the client either does not receive the payload or receives the first few characters. For all response strings of length < 1000, it has worked well. I tried to hard code the string, read it from a file, generate it programmatically etc. I tried to return as "text/plain", "application/json","text/html", but no help. It is possible that the magic number 1000 may be just a random coincidence, but it was consistent in over 30 tests I did. When I tried to do the same long responses (>1000) by modifying the example code given in "ph_test.cpp", and it has no such problem. What am I doing wrong?

struct DataHandler : CrackedUriPageHandler {    
    DataHandler(){}; //my code has one argument for the constructor, which is irrelevant here
    virtual std::shared_ptr<Response> handle(const CrackedUri &uri,
                                             const Request &request) override {
        std::string resp = "";
        for(int i=0; i< 999; i++) { // <= 999 is OK, but >=1000 is giving the error  
            resp += "m";
        }
        return Response::textResponse(resp);        
    };
};

//server starting code
auto root = make_shared<RootPageHandler>();
auto pathHandler = make_shared<PathHandler>("show", make_shared<DataHandler>());        
root->add(pathHandler);  
server.addPageHandler(root);
server.serve(server_root.data(), server_port); //server_root and server port come from elsewhere

The response is like (where the length 1020 is correct, but the content is missing after one char):

200 OK
Server:  Seasocks/unversioned
Date:  Tue, 19 Apr 2016 01:58:52 GMT
Access-Control-Allow-Origin:  *
Content-Length:  1,020
Content-Type:  text/plain
Connection:  keep-alive
Last-Modified:  Tue, 19 Apr 2016 01:58:52 GMT
Pragma:  no-cache
Cache-Control:  no-store
Expires:  Tue, 19 Apr 2016 01:58:52 GMT

m

Compiler info: gcc 4.8.5 20150623 (Red Hat 4.8.5-4)
CMake options: ADD_DEFINITIONS(-Wall -Wextra -pedantic -ggdb3 -fPIC)

Multipart responses

I've been enjoying using seasocks for websocket content.

I want to stream mjpegs from seasocks. To do this, I need to send a multipart http response. Seasocks looks like it really wants you to generate the entire page response and then it will send that all at once. Is there a way to send a multipart response (where the response comes back in chunks spread out over time)? I don't see it from the interface provided for the response.

Firefox support

Seems the websocket stuff is broken in Firefox (tested in v33)

Run code periodically on seasocks thread

Hi! I was wondering if there is an easy/"best" way to periodically run some code on the seasocks thread. What I want to do is check if there are no current connections and if there haven't been any for the last 10 minutes or so then shutdown the server (It will get started again on demand when needed).

I can think of a couple ways now:

  • Create another epoll() descriptor and embed seasocks's epoll() inside it as done in the ws_test_poll.cpp test (a bit annoying to code on the application side, but not intolerable)
  • Create another thread that's basically while(1) { sleep(60); server->execute(...); } (requires starting another thread in each seasocks process)

I just wanted to check if there was any easy way to hook into seasocks' epoll_wait() loop as it stands and, if not, if this would be something you'd consider adding to the API.

Thanks!

Support Filedata return from a PageHandler

Though you can set up static file hosting based on the incoming URI, there appears to be no way to use the sendStaticData function from a dynamic Response from a PageHandler.

I would like to set up my server so that a CrackedUriPageHandler figures out what file the user wants based off of something in the request (like the query params) and uses something like sendStaticData to send a static file from the filesystem back to the client.

I noticed a relevant TODO in that method:

// TODO: fold this into the handler way of doing things.

Occasional test failures at Travis CI

Occasionally there are test failures on travis ci builds. Random builds fail at the ctest -D ExperimentalMemCheck step – with compiler varying from build to build.

After one or two re-runs, the build is ok. No failure locally.

Output on failure:

$ ctest -D ExperimentalMemCheck
   Site: testing-gce-8767ab6f-b1a6-4f55-81d6-fa8f865a2e58
   Build name: Linux-g++-4.7
Memory check project /home/travis/build/offa/seasocks/build
    Start 1: AllTests
1/1 MemCheck #1: AllTests .........................***Failed   21.70 sec

0% tests passed, 1 tests failed out of 1

Total Test time (real) =  21.70 sec

The following tests FAILED:
	  1 - AllTests (Failed)
-- Processing memory checking output: 
Memory checking results:
Errors while running CTest

Examples

Improve handler efficience with a map

Browsing the code, it looks like the Page Handlers cascade by calling the handle() function in all of the handlers in its vector. The first thing this handler does is check if the cracked uri portion matches its part and return unhandled() if it does not match.

Could this be made more efficient by storing the handlers as a map of URI portion -> handler so that when a request comes in, the handler can crack off part of the url and call the handle method on all of the handlers inserted into the map under the key matching that map?

It's definitely possible I am misunderstanding the code so please correct me if I'm mistaken.

URL containing two slashes together not working

If a URL contains two slashes together, like http://localhost:8080/a//b/c or http://localhost:8080//a/b/c, it is not treated the same way as the one slashed version http://localhost:8080/a/b/c.

Is this the expected behavior?

Received hybi frame with unknown opcode 10

Firstly, seasocks is great! Loving the easy c++ connectivity.

Running seasocks on a Pi, using Win10 based clients. Chrome is fine, but both IE and Edge cause "Received hybi frame with unknown opcode 10", followed by a disconnect.

Assume 99% this is a ME issue, so any ideas where I should start looking?

Cheers.

Bruce.

compile error.

I was following the getting started instructions, however '$ cmake ..' fails:

In file included from /mnt/vbox/shared/github/seasocks/src/main/c/Connection.cpp:49:0:
/mnt/vbox/shared/github/seasocks/src/main/c/Connection.cpp: In member function ‘bool seasocks::Connection::sendError(seasocks::ResponseCode, const string&)’:
/mnt/vbox/shared/github/seasocks/src/main/c/Connection.cpp:696:22: error: ‘HANDLING_HIXIE_WEBSOCKET’ was not declared in this scope
     assert(_state != HANDLING_HIXIE_WEBSOCKET);

I changed it to get it to compile:

$ git diff
diff --git a/src/main/c/Connection.cpp b/src/main/c/Connection.cpp
index ca760cf..405e7e4 100644
--- a/src/main/c/Connection.cpp
+++ b/src/main/c/Connection.cpp
@@ -693,7 +693,7 @@ void Connection::handleWebSocketBinaryMessage(const std::vector<uint8_t>& messag
 }
 
 bool Connection::sendError(ResponseCode errorCode, const std::string& body) {
-    assert(_state != HANDLING_HIXIE_WEBSOCKET);
+    assert(_state != State::HANDLING_HIXIE_WEBSOCKET);
     auto errorNumber = static_cast<int>(errorCode);
     auto message = ::name(errorCode);
     bufferResponseAndCommonHeaders(errorCode);

Add SONAME support

ABI-breaking updates would be easier to handle if you used CMake’s SOVERSION feature to install the library with a versioned SONAME and appropriate symlinks.

I’ve included a potential patch, but it assumes you use semantic versioning and will bump the major version number for any incompatible ABI changes.

diff --git a/src/main/c/CMakeLists.txt b/src/main/c/CMakeLists.txt
index 3bec50d..c8db260 100644
--- a/src/main/c/CMakeLists.txt
+++ b/src/main/c/CMakeLists.txt
@@ -39,7 +39,10 @@ target_include_directories(seasocks_so PUBLIC ${ZLIB_INCLUDE_DIRS} .)
 if (DEFLATE_SUPPORT)
     target_link_libraries(seasocks_so PRIVATE ${CMAKE_THREAD_LIBS_INIT} "${ZLIB_LIBRARIES}")
 endif()
-set_target_properties(seasocks_so PROPERTIES OUTPUT_NAME seasocks)
+set_target_properties(seasocks_so
+                      PROPERTIES OUTPUT_NAME seasocks
+                      VERSION ${PROJECT_VERSION}
+                      SOVERSION 1)
 
 install(TARGETS seasocks seasocks_so
         LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}

This will cause let developers use -lseasocks when linking, looking for libseasocks.so. Programs will try to link with libseasocks.so.1 at load time, finding any installed library with a major version of 1. Both of these will be symlinks to the actual libseasocks.so.1.3.2 or whatever version is actually installed.

Documentation

Hey there !

I took a look but couldn't find any form of documentation, the only "guide" related to the project being the quick example.

Is a documentation in preparation or won't this library have any documentation ?

Notifying all WebSocket clients from another thread

Hi!
How I can notifying all websocket clients about new data getting from another thread? If I call every registered connection 'connection->send()' from another thread, server throwed exception and wrote 'seasocks called on wrong thread'. =(

MaxWebsocketMessageSize is hard-coded

If you want bigger inbound messages you need to bump this up in src/main/c/Connection.cpp (and maybe also ReadWriteBufferSize -- dunno I did both), and then recompile library.

ResponseBuilder operator<<

I'm trying to use ResponseBuilder& operator << but I don't see how to.

It seems to accept a C++11 rvalue type so I tried:

std::shared_ptr<seasocks::Response> jsonResp(json body, seasocks::ResponseCode status = seasocks::ResponseCode::Ok) {
    seasocks::ResponseBuilder respBuilder(status);
    respBuilder.withContentType("application/json");
    respBuilder << body.dump(); // body.dump() returns a std::string
    return respBuilder.build();
}

but I got this compile error.

In file included from opencast.cpp:8:0:
deps/seasocks/src/main/c/seasocks/ResponseBuilder.h: In instantiation of ‘seasocks::ResponseBuilder& seasocks::ResponseBuilder::operator<<(T&&) [with T = std::__cxx11::basic_string<char>]’:
opencast.cpp:205:30:   required from here
deps/seasocks/src/main/c/seasocks/ResponseBuilder.h:71:35: error: no matching function for call to ‘forward(std::__cxx11::basic_string<char>&)’
         (*_stream) << std::forward(t);
                       ~~~~~~~~~~~~^~~
In file included from /usr/include/c++/6.3.1/bits/nested_exception.h:40:0,
                 from /usr/include/c++/6.3.1/exception:171,
                 from /usr/include/c++/6.3.1/ios:39,
                 from /usr/include/c++/6.3.1/ostream:38,
                 from /usr/include/c++/6.3.1/iostream:39,
                 from deps/seasocks/src/main/c/seasocks/Credentials.h:28,
                 from deps/seasocks/src/main/c/seasocks/Request.h:28,
                 from deps/seasocks/src/main/c/seasocks/WebSocket.h:28,
                 from deps/seasocks/src/main/c/seasocks/ServerImpl.h:28,
                 from deps/seasocks/src/main/c/seasocks/Server.h:28,
                 from opencast.cpp:3:
/usr/include/c++/6.3.1/bits/move.h:76:5: note: candidate: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_From>::type&)
     forward(typename std::remove_reference<_Tp>::type& __t) noexcept
     ^~~~~~~
/usr/include/c++/6.3.1/bits/move.h:76:5: note:   template argument deduction/substitution failed:
In file included from opencast.cpp:8:0:
deps/seasocks/src/main/c/seasocks/ResponseBuilder.h:71:35: note:   couldn't deduce template parameter ‘_Tp’
         (*_stream) << std::forward(t);
                       ~~~~~~~~~~~~^~~
In file included from /usr/include/c++/6.3.1/bits/nested_exception.h:40:0,
                 from /usr/include/c++/6.3.1/exception:171,
                 from /usr/include/c++/6.3.1/ios:39,
                 from /usr/include/c++/6.3.1/ostream:38,
                 from /usr/include/c++/6.3.1/iostream:39,
                 from deps/seasocks/src/main/c/seasocks/Credentials.h:28,
                 from deps/seasocks/src/main/c/seasocks/Request.h:28,
                 from deps/seasocks/src/main/c/seasocks/WebSocket.h:28,
                 from deps/seasocks/src/main/c/seasocks/ServerImpl.h:28,
                 from deps/seasocks/src/main/c/seasocks/Server.h:28,
                 from opencast.cpp:3:
/usr/include/c++/6.3.1/bits/move.h:87:5: note: candidate: template<class _Tp> constexpr _Tp&& std::forward(typename std::remove_reference<_From>::type&&)
     forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
     ^~~~~~~
/usr/include/c++/6.3.1/bits/move.h:87:5: note:   template argument deduction/substitution failed:
In file included from opencast.cpp:8:0:
deps/seasocks/src/main/c/seasocks/ResponseBuilder.h:71:35: note:   couldn't deduce template parameter ‘_Tp’
         (*_stream) << std::forward(t);
                       ~~~~~~~~~~~~^~~

Shouldn't this work? Can you please show an example of how to use ResponseBuilder?

Compiling seasocks on MinGW

I get an error about missing arpa/inet.h - do you not use winsock2.h on Windows? Or is seasocks not made portable to Windows?

HTTPS support

Requested over email a couple of times. Issues would be:

  • how to ensure we pick a good SSL library, and configure and use it an a secure manner
  • ensure the use of HTTPS is compile-time configurable so embedded users don't have to have a working SSL implementation around
  • ensure its easy to configure certificates etc

Make ZLIB/deflate support optional

Some users don't need deflate and might want to remove a library dependence. Making the zlib optional seems somewhat straightforward.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.