Share your repls and programming experiences

← Back to all posts
HTTP Server Library in C++
h
CSharpIsGud (549)

This is a small single-file header-only HTTP library for C++!

REMEMBER THIS WONT WORK FOR HTTPS

Simply copy htpp.hpp to your project and include it, then your good to go!

Update: This library now supports basic CGI as suggested by @JadenGarcia

@Highwayman I was thinking about maybe making a second class / lib type thing that parses/generates HTTP packets for you, but don’t count on it. Here it is.

Commentshotnewtop
oignons (306)

Woah. This is cool, great job! I did t know that you could do this with c++.

#C++Gang

[deleted]

π

xxpertHacker (382)

@Zuhdi28 This is totally relevant.

Highwayman (1340)

Quick question: why are you making the Dict class without std::unordered_map? Also you can probably return "" for Get() and GetHTTPRep() and then the user will just test for string.empty() == true to see if there’s an error or what ever that is for.

Edit: isn’t it "\r\n", not "\n"? (CRLF)

CSharpIsGud (549)

@Highwayman I didn't remember what a C++ dictionary was named so I made my own.

xxpertHacker (382)

@Highwayman "\r\n" or "\n\r" is Windows, '\n' is Linux, this is implementation dependent. If you explicitly need to move down you could use an escape sequence, I think "\e[B" is down.

Highwayman (1340)

@StudentFires I’m talking about according to the HTTP standards what actual binary codes are being used, not what it looks like.

xxpertHacker (382)

@Highwayman So the HTTP standards actually care? Do you have a source?

Highwayman (1340)

@StudentFires uhm yes. The HTTP/1.1 standard, rfc 7230

xxpertHacker (382)

@Highwayman A quick Ctrl-F search isn't finding anything. I'm looking at w3.

Highwayman (1340)

@StudentFires sorry wait the thing is 200 pages or something let me find the right spot for you....

xxpertHacker (382)

@Highwayman Checked that too, before you linked me.

Highwayman (1340)

@StudentFires ah, how far did you scroll lol

xxpertHacker (382)

@Highwayman As did I, pretty sure compiled code on a Linux will just secretly omit the \r anyways, so we may have a problem.

Highwayman (1340)

@StudentFires nah, that’s Windows your thinking of actually. When reading in files on Windows, they will quietly drop the \r in \r\n. That can be surpassed by opening files in binary mode though.

xxpertHacker (382)

@Highwayman Usually there is a difference between the standard and the implementation. But ECMA and HTTP are quite different.

Highwayman (1340)

@StudentFires 🤷‍♂️ Ok. I wouldn’t know I’d say lol.

Highwayman (1340)

Noiiiiice, you beat me too it! awesome!

Highwayman (1340)

You should repost this / ,ove this to templates :D

CSharpIsGud (549)

@Highwayman I would but im not sure its very templatey

Highwayman (1340)

@CSharpIsGud waddaya mean it’s super templatey. I think you should. It would be a great addition to repl.it templates. Think about it like this: express template is a thing.

CSharpIsGud (549)

@Highwayman do templates have to be single file and or noob friendly? I doubt this would be very clean to cram into the main file and sockets aren't a very noob friendly thng

Highwayman (1340)

@CSharpIsGud the only thing they’d be editing is the main file. All they’d be doing is adding paths and stuff, not necessarily changing how the sockets and http parsing works / functions.

JadenGarcia (39)

Forgot to mention, CGI files are supposed to be able to write headers, thus, by extension, also set cookies. For example,

Content-Type: application/xhtml+xml
Set-Cookie: key=val; secure; httpOnly


<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
  <head>
    <meta name="viewport" content="width=device-width,height=device-height"/>
  <title>Hello, World!</title>
  </head>
  <body>
    <h1>Hello, World!</h1>
  </body>
</html>

If this were generated by a CGI script, it should set the header and send the cookie.

CSharpIsGud (549)

@JadenGarcia The cgi things ive seen had the t in content type uncapitalized, did they all have a typo?

CSharpIsGud (549)

@JadenGarcia I have a basic implementation that allows me to set headers and output ready

#!/usr/bin/python3
import os

print("Content-Type: text/html")
print("Status: 200 OK")
print()

print("<b>Python CGI<b>")
print("<br><br>");
print("<b><em>Method: " + os.environ["REQUEST_METHOD"] + "</em></b>")
xxpertHacker (382)

@CSharpIsGud Hmm... I honestly don't know if it's a typo or not. Think browsers will work either way, but they might not.

CSharpIsGud (549)

@StudentFires Oh, no its not a browser thing, a browser wouldn't but the cgi spec shows a lot of examples where they use Content-type instead of Content-Type but they should really both work if it is to conform to cgi standard

xxpertHacker (382)

@CSharpIsGud It has to be a browser thing, I'm not sure if a browser is supposed to accept headers case insensitively, or not.

Eh, it might be server dependent, as the server sends the headers, not the CGI. I'm not 100% familiar with the CGI standard.

xxpertHacker (382)

@CSharpIsGud Tested on Google Chrome, headers are case insensitive. A quick search gave this: https://stackoverflow.com/questions/5258977/are-http-headers-case-sensitive, so it shouldn't matter.

Also update the post to say @StudentFires recommended CGI. If you think this doesn't properly give credit to the current person who said it, read his Repl bio.

Highwayman (1340)

@CSharpIsGud the headers names are case insensitive.

JadenGarcia (39)

IS there any way to make this CGI compatible? I have an active question about this here.

CSharpIsGud (549)

@JadenGarcia Im sure it could be possible to make a cgi protocol extension for this or something

JadenGarcia (39)

@CSharpIsGud Do you have an estimate of how complicated it would be?

CSharpIsGud (549)

@JadenGarcia I haven't looked at any specs for it yet, but looking at the wiki

Calling a command generally means the invocation of a newly created process on the server. Starting the process can consume much more time and memory than the actual work of generating the output, especially when the program still needs to be interpreted or compiled. If the command is called often, the resulting workload can quickly overwhelm the server. You might want to look for some alternative ways to do what you want first.

JadenGarcia (39)

@CSharpIsGud That may very well be true, but if we look at that in depth, piece by piece and compare it to what I'm actually working with, we will see that not all of this applies to me. "Starting the process can consume much more time and memory", well, C++ is extremely well suited to taking as little memory as possible, especially if coded with this in mind, so let's hope that isn't the case. "still needs to be interpreted or compiled", the program is already compiled, with heavy optimization flags.

This should achieve speeds faster than PHP if done properly, and better workload management than NodeJS.

CSharpIsGud (549)

@JadenGarcia How complex is the specification?

JadenGarcia (39)

@CSharpIsGud At it's most basic, it says, "when a server is told to send a file that ends with the extension '.cgi' execute the binary file and send the output from the file, as opposed to sending the binary". I'm just not sure how to capture the output.

CSharpIsGud (549)

@JadenGarcia I believe this is what popen is for

JadenGarcia (39)

@CSharpIsGud Indeed, it would appear so.

CSharpIsGud (549)

@JadenGarcia Is there a good reason for you to be using lambdas everywhere instead of actual functions?

CSharpIsGud (549)

@JadenGarcia Why did you use so many where normal functions would look way better?

JadenGarcia (39)

@CSharpIsGud If it's just for looks then why does it matter? I'm not a company, no one will ever have to maintain this code.

CSharpIsGud (549)

@JadenGarcia

const auto Root = [](Request* const req) noexcept -> void
{
    req->Respond(200, getFile());
};

vs

void Root(Request* req) {
    req->Respond(200, getFile());
}

I bet thats people said about every open source project that started small.

Im sure there are probably some other performance whatevers about lambdas too but its probably fairly insignificant

JadenGarcia (39)

@CSharpIsGud How about this?

auto Root(Request* const req) noexcept -> const void
{
    req->Respond(200, getFile());
}

It's not a lambda.

CSharpIsGud (549)

@JadenGarcia still no idea why you need noexcept, auto and const void but its better

JadenGarcia (39)

@CSharpIsGud If something doesn't need to change, it should be declared as read-only or const. The noexcept if for clarification. Honestly I think const void is an error, but if I recall you can't use a void pointer on it, it has to be a const void.

Also, totally separate and unrelated, do you know how to use variardic functions well? Can I invite you to a simple C++ Repl?

JadenGarcia (39)

@CSharpIsGud Can I safely turn this

auto html = [](auto  text, auto ...extras)

into:

auto html = [](auto ...extras, auto text)
CSharpIsGud (549)

@JadenGarcia oh also the -> const void things aren't really necessary either, you can use noexcept on its own without it

JadenGarcia (39)

@CSharpIsGud I'm aware. Also, usually auto defaults to void too.

CodeSalvageON (560)

Yes...yes..good...good...

[deleted]

Good Work @CSharpIsGud !
i think c++ is so hard...
And i did!
Good Job!

xxpertHacker (382)

@Zuhdi28 C++ isn't hard! C is harder.

CSharpIsGud (549)

@StudentFires Compared to other languages they are both just as hard. the main difference between C and C++ is that C++ has a better standard library(and object orientation)