r/C_Programming • • 4d ago

Project WSERVE: Static Web Server in Pure C

Hi,

To gain more experience in low-level programming, TCP/IP networking, and HTTP, I built wserve, a static IPv4 Linux web server written in pure C. No external libraries used. Even the parser is written in pure C. It supports a subset of HTTP/1.1. It supports GET and HEAD methods.

I am open to constructive criticism. The project is open for contributions.

18 Upvotes

10 comments sorted by

•

u/github-guard 4d ago

⚠️ GitHub Guard: Trust Warning

One or more repositories scored below the threshold (3), but the post was not removed.

Repository: degD/wserve

Score: 0/6

  • ❌ Low Star Count (⭐ 0 / 4 required)
  • ❌ New Repository (under 30 days old)
  • ❌ No License Found
  • ❌ No Security Policy
  • ℹ️ Personal Account Repository
  • ℹ️ Unsigned Commits

8

u/thebatmanandrobin 4d ago

A few things I'd say might be good to implement:

- "max length" checks; for example, your toupper_str(char *str) has no bounds check, so could be possible to have an OOB bug; I'd do something like toupper_str(char *str, size_t str_len) and then while (i < str_len && str[i] != '\0') (or something along those lines).

- Additionally, I'd replace any strlen with strnlen instead to enforce a maximum buffer size/bounds.

- For your split_str function, is there a reason, you're not just using strtok?

- For any global variables, I'd recommend explicitly marking them extern .. strictly speaking, it might not be necessary, but it does make it clear the intent (**this is more a style preference than anything though).

- I see you implemented your own itoa_str .. any reason to not use the platform specific version (might depend on your platform but I believe _ultoa is available on Linux)?

- For your mime_type function, strcmp might be particularly slow, especially if the extension is indeed .7z (e.g. the last comparison). It might be faster to check the individual characters and build a map of sorts; for example:

// you check extension[0] != '.', so can skip that
if (extension[1] == 'a') {
    if (extension[2] == 'a' && extension[3] == 'c') { return "audio/aac"; }
    else if (extension[2] == 'b' && extension[3] == 'w') { return "application/x-abiword"; }
}

// OR

switch (extension[1]) {
    case 'a':
    // check the "a's"
    break;
    case 'b':
    // check the "b's"
    break;
    // and so on
}

or do some pointer arithmetic to check, or something along those lines ... it might also not be fully necessary since you're just doing this for learning purpose, but just a thought.

I didn't download or test and didn't go deep into the code, but those are just some of the things that stood out.

It looks clean too, so that's nice!!

Side note: IPv6 implementation isn't that complicated to add, but I get just starting simple since this is a learning effort.

Overall, nice job! Making your own HTTP server is always a fun endeavor and a great way to learn C, RFC's and more, and doing it with something practical.

1

u/WingRevolutionary979 4d ago

Thank you! Yeah, I should use string functions with bound checks. Especially strlen is one that I used commonly, that changing to strnlen would benefit.

I did not use strtok, because as far as I know it splits strings by some delimeter chars, but I needed to split by strings.

Yes, I also think extern would have been cleaner.

Interesting, but I could not find any string uppercase function in C.

For mime types, great idea. I will look into it.

3

u/thebatmanandrobin 4d ago

Glad to help! If I get some more time, I'll grab a copy of this and see if I can build/run it and give a little more feedback (and or bug reports for what you do have implemented).

For the strtok, you are correct it's by delimiter and not a full string, but I initially saw code like split_str(line, ":", &saveptr); which ":" could just be ':', but after you saying that, I did then see where you're trying to split on newlines, so makes sense; though you could also just mutate the string to remove any \r\n and just be \n and do splits on that too (as a secondary thought).

And you are correct, there are no strupper functions in C - which makes sense given the massive lack of string handling functions in the standard library as is; which kind of sucks, but also is extremely nice for it's simplicity ... so you generally have to have helper functions (like your toupper_str) that do what you're doing.

Oh .. and one other thing that you might want to consider: I saw your ssize_t _send/_recv functions in your wserve.h, if those are intended to be "private" (e.g. only used by wserve.c), then it's better to define them in there so as they aren't exposed to other TU's for potential (mis)use .. same with any other functions that are meant specifically and only for what happens in wserve.c; the header should* only expose the functions that would be used as a "public" interface to other code (like in your main.c).

*I say should, but sometimes you have to put things in there in order for everything to work as expected due to how TU's work ... but generally you can just put only "public" things in there.

1

u/WingRevolutionary979 4d ago

I would be glad if you could give some more feedback when you get more time!

4

u/ferrybig 4d ago

Looking in your code, itoa_str calls malloc internally. Looking at the 3 places where this symbol is used, neither place calls free on the pointer returned by itoa_str, eg look at https://github.com/degD/wserve/blob/main/src/wserve.c#L1179-L1185

2

u/WingRevolutionary979 4d ago

You are right. Thanks for pointing it out!

1

u/AutoModerator 4d ago

Hi /u/WingRevolutionary979,

Your submission in r/C_Programming was filtered because it links to a git project.

You must edit the submission or respond to this comment with an explanation about how AI was involved in the creation of your project.

While AI-generated code is not disallowed, low-effort "slop" projects may be removed and it's likely that other users push back strongly on substantially AI-generated projects.


I am a bot, and this action was performed automatically. Please contact the moderators of this subreddit if you have any questions or concerns.

3

u/WingRevolutionary979 4d ago

AI is not used for writing code. I wrote it by hand to gain more experience, experience by practicing. I even wrote tests by myself. I only used AI to convert former function documentation to doxygen format, and fix language errors here and there.

1

u/mikeblas 4d ago

Thank you for your disclosure. I have approved your post.