├── .gitignore ├── scott.jpg ├── Makefile ├── page2.html ├── index.html ├── README.md └── server.c /.gitignore: -------------------------------------------------------------------------------- 1 | #Don't upload log files 2 | *.log 3 | -------------------------------------------------------------------------------- /scott.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labcoder/simple-webserver/HEAD/scott.jpg -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for server 2 | server: server.c 3 | gcc server.c -o server 4 | 5 | -------------------------------------------------------------------------------- /page2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Oscar's web server example 4 | 5 |
6 |

PAGE 2

7 |

8 | This is page 2! Welcome :) 9 |

10 | 11 |
12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Oscar's web server example 4 | 5 |
6 |

Welcome to the default homepage!

7 | 8 |

Here's an image of scott pilgrim... he's really cool and you can learn about him here.

9 |
10 |

11 | Just some basic default page. For another page... go here. 12 |

13 | 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |

Simple webserver

3 |

This example of a simple webserver is inspired by IBM's really small webserver example, nweb.

4 |
5 |

Uses

6 |

This is obviously not meant to be used for real deployment, and is just out here in case someone wants to see a small c-based webserver in use. Basic socket use examples are in here from nweb. Also included are two small pages to serve up.

7 |
8 |

Example

9 |

Run the Makefile

10 |
make
11 |

You run the server like this:

12 |
./server [port] [location to serve pages from] [& - to run in background]
13 |

For example, to run it on port 8080, you'd do something like this:

14 |
./server 8080 ./ &
15 | 16 | -------------------------------------------------------------------------------- /server.c: -------------------------------------------------------------------------------- 1 | /* 2 | * project: miniweb 3 | * author: Oscar Sanchez (oms1005@gmail.com) 4 | * HTTP Server 5 | * WORKS ON BROWSERS TOO! 6 | * Inspired by IBM's nweb 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define BUFSIZE 8096 22 | #define ERROR 42 23 | #define SORRY 43 24 | #define LOG 44 25 | 26 | struct { 27 | char *ext; 28 | char *filetype; 29 | } extensions [] = { 30 | {"gif", "image/gif" }, 31 | {"jpg", "image/jpeg"}, 32 | {"jpeg","image/jpeg"}, 33 | {"png", "image/png" }, 34 | {"zip", "image/zip" }, 35 | {"gz", "image/gz" }, 36 | {"tar", "image/tar" }, 37 | {"htm", "text/html" }, 38 | {"html","text/html" }, 39 | {"php", "image/php" }, 40 | {"cgi", "text/cgi" }, 41 | {"asp","text/asp" }, 42 | {"jsp", "image/jsp" }, 43 | {"xml", "text/xml" }, 44 | {"js","text/js" }, 45 | {"css","test/css" }, 46 | 47 | {0,0} }; 48 | 49 | void log(int type, char *s1, char *s2, int num) 50 | { 51 | int fd ; 52 | char logbuffer[BUFSIZE*2]; 53 | 54 | switch (type) { 55 | case ERROR: (void)sprintf(logbuffer,"ERROR: %s:%s Errno=%d exiting pid=%d",s1, s2, errno,getpid()); break; 56 | case SORRY: 57 | (void)sprintf(logbuffer, "

Web Server Sorry: %s %s

\r\n", s1, s2); 58 | (void)write(num,logbuffer,strlen(logbuffer)); 59 | (void)sprintf(logbuffer,"SORRY: %s:%s",s1, s2); 60 | break; 61 | case LOG: (void)sprintf(logbuffer," INFO: %s:%s:%d",s1, s2,num); break; 62 | } 63 | 64 | if((fd = open("server.log", O_CREAT| O_WRONLY | O_APPEND,0644)) >= 0) { 65 | (void)write(fd,logbuffer,strlen(logbuffer)); 66 | (void)write(fd,"\n",1); 67 | (void)close(fd); 68 | } 69 | if(type == ERROR || type == SORRY) exit(3); 70 | } 71 | 72 | void web(int fd, int hit) 73 | { 74 | int j, file_fd, buflen, len; 75 | long i, ret; 76 | char * fstr; 77 | static char buffer[BUFSIZE+1]; 78 | 79 | ret =read(fd,buffer,BUFSIZE); 80 | if(ret == 0 || ret == -1) { 81 | log(SORRY,"failed to read browser request","",fd); 82 | } 83 | if(ret > 0 && ret < BUFSIZE) 84 | buffer[ret]=0; 85 | else buffer[0]=0; 86 | 87 | for(i=0;i 0 ) { 129 | (void)write(fd,buffer,ret); 130 | } 131 | #ifdef LINUX 132 | sleep(1); 133 | #endif 134 | exit(1); 135 | } 136 | 137 | 138 | int main(int argc, char **argv) 139 | { 140 | int i, port, pid, listenfd, socketfd, hit; 141 | size_t length; 142 | static struct sockaddr_in cli_addr; 143 | static struct sockaddr_in serv_addr; 144 | 145 | if( argc < 3 || argc > 3 || !strcmp(argv[1], "-?") ) { 146 | (void)printf("usage: server [port] [server directory] &" 147 | "\tExample: server 80 ./ &\n\n" 148 | "\tOnly Supports:"); 149 | for(i=0;extensions[i].ext != 0;i++) 150 | (void)printf(" %s",extensions[i].ext); 151 | 152 | (void)printf("\n\tNot Supported: directories / /etc /bin /lib /tmp /usr /dev /sbin \n" 153 | ); 154 | exit(0); 155 | } 156 | if( !strncmp(argv[2],"/" ,2 ) || !strncmp(argv[2],"/etc", 5 ) || 157 | !strncmp(argv[2],"/bin",5 ) || !strncmp(argv[2],"/lib", 5 ) || 158 | !strncmp(argv[2],"/tmp",5 ) || !strncmp(argv[2],"/usr", 5 ) || 159 | !strncmp(argv[2],"/dev",5 ) || !strncmp(argv[2],"/sbin",6) ){ 160 | (void)printf("ERROR: Bad top directory %s, see server -?\n",argv[2]); 161 | exit(3); 162 | } 163 | if(chdir(argv[2]) == -1){ 164 | (void)printf("ERROR: Can't Change to directory %s\n",argv[2]); 165 | exit(4); 166 | } 167 | 168 | if(fork() != 0) 169 | return 0; 170 | (void)signal(SIGCLD, SIG_IGN); 171 | (void)signal(SIGHUP, SIG_IGN); 172 | for(i=0;i<32;i++) 173 | (void)close(i); 174 | (void)setpgrp(); 175 | 176 | log(LOG,"http server starting",argv[1],getpid()); 177 | 178 | if((listenfd = socket(AF_INET, SOCK_STREAM,0)) <0) 179 | log(ERROR, "system call","socket",0); 180 | port = atoi(argv[1]); 181 | if(port < 0 || port >60000) 182 | log(ERROR,"Invalid port number try [1,60000]",argv[1],0); 183 | serv_addr.sin_family = AF_INET; 184 | serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 185 | serv_addr.sin_port = htons(port); 186 | if(bind(listenfd, (struct sockaddr *)&serv_addr,sizeof(serv_addr)) <0) 187 | log(ERROR,"system call","bind",0); 188 | if( listen(listenfd,64) <0) 189 | log(ERROR,"system call","listen",0); 190 | 191 | for(hit=1; ;hit++) { 192 | length = sizeof(cli_addr); 193 | if((socketfd = accept(listenfd, (struct sockaddr *)&cli_addr, &length)) < 0) 194 | log(ERROR,"system call","accept",0); 195 | 196 | if((pid = fork()) < 0) { 197 | log(ERROR,"system call","fork",0); 198 | } 199 | else { 200 | if(pid == 0) { 201 | (void)close(listenfd); 202 | web(socketfd,hit); 203 | } else { 204 | (void)close(socketfd); 205 | } 206 | } 207 | } 208 | } 209 | --------------------------------------------------------------------------------