0% found this document useful (0 votes)
58 views

Internet Services II April 27, 2000 15-213: Topics

The document discusses serving dynamic content from a web server. It explains that if a request URI contains "/cgi-bin/", the server assumes it is a request for dynamic content. The server then creates a child process to run the program identified by the URI. The child generates the dynamic content, which the server captures and sends to the client without modification. Issues like passing arguments between client/server/child and environment variables are addressed by the Common Gateway Interface (CGI) specification. The document also provides an overview of the Tiny Web server, which is written in C to serve static and dynamic content using the GET method.

Uploaded by

jaimin28
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views

Internet Services II April 27, 2000 15-213: Topics

The document discusses serving dynamic content from a web server. It explains that if a request URI contains "/cgi-bin/", the server assumes it is a request for dynamic content. The server then creates a child process to run the program identified by the URI. The child generates the dynamic content, which the server captures and sends to the client without modification. Issues like passing arguments between client/server/child and environment variables are addressed by the Common Gateway Interface (CGI) specification. The document also provides an overview of the Tiny Web server, which is written in C to serve static and dynamic content using the GET method.

Uploaded by

jaimin28
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 29

15-213

Internet Services II

April 27, 2000

Topics
• dynamic content
• Tiny Web server tour

class28.ppt
Serving dynamic content

Client sends request to


server. GET /cgi-bin/env.pl HTTP/1.1

If request URI contains


the string “/cgi-bin”, client server
then the server assumes
that the request is for
dynamic content.

class28.ppt –2– CS 213 S’00


Serving dynamic content

The server creates a child


process and runs the client server
program identified by the
URI in that process
fork/exec

env.pl

class28.ppt –3– CS 213 S’00


Serving dynamic content

The child runs and


generates the dynamic client
content
server
content.
The server captures the content
content of the child and
forwards it without env.pl
modification to the client

class28.ppt –4– CS 213 S’00


Serving dynamic content

The child terminates.


Server waits for the next client server
client request.

class28.ppt –5– CS 213 S’00


Issues in serving dynamic content

How does the client pass program


request
arguments to the server?
content server
How does the server pass these client
arguments to the child?
How does the server pass other content create
info relevant to the request to
the child? env.pl
How does the server capture the
content produced by the child?
These issues are addressed by
the Common Gateway Interface
(CGI) specification.

class28.ppt –6– CS 213 S’00


CGI
Because the children are written according to the
CGI spec, they are often called CGI programs.

Because many CGI programs are written in Perl, they


are often called CGI scripts.

However, CGI really defines a simple standard for


transferring information between the client
(browser), the server, and the child process.

class28.ppt –7– CS 213 S’00


add.com:
THE Internet addition portal!
Ever need to add two numbers together and you just
can’t find your calculator?
Try Dr. Dave’s addition service at add.com: THE
Internet addition portal!
• Takes as input the two numbers you want to add together.
• Returns their sum in a tasteful personalized message.
After the IPO we’ll expand to multiplication!

class28.ppt –8– CS 213 S’00


The add.com
input URL experience
host port CGI program args

Output page

class28.ppt –9– CS 213 S’00


Serving dynamic content with GET
Question: How does the client pass arguments to
the server?
Answer: The arguments are appended to the URI

Can be encoded directly in a URL typed to a


browser or a URL in an HTML link
• http://add.com/cgi-bin/adder?1&2
• adder is the CGI program on the server that will do the
addition.
• argument list starts with “?”
• arguments separated by “&”
• spaces represented by “+” or “%20”
Can also be generated by an HTML form

<form method=get action="http://add.com/cgi-bin/postadder">

class28.ppt – 10 – CS 213 S’00


Serving dynamic content with GET
URL:
• http://add.com/cgi-bin/adder?1&2

Result displayed on browser:

Welcome to add.com: THE Internet addition portal.

The answer is: 1 + 2 = 3

Thanks for visiting! Tell your friends.

class28.ppt – 11 – CS 213 S’00


Serving dynamic content with GET
Question: How does the server pass these
arguments to the child?
Answer: In environment variable QUERY_STRING
• a single string containing everything after the “?”
• for add.com: QUERY_STRING = “1&2”

/* child code that accesses the argument list */


if ((buf = getenv("QUERY_STRING")) == NULL) {
exit(1);
}

/* extract arg1 and arg2 from buf and convert */


...
n1 = atoi(arg1);
n2 = atoi(arg2);

class28.ppt – 12 – CS 213 S’00


Serving dynamic content with GET
Question: How does the server pass other info
relevant to the request to the child?
Answer: in a collection of environment variables
defined by the CGI spec.

class28.ppt – 13 – CS 213 S’00


Some CGI environment variables
General
• SERVER_SOFTWARE
• SERVER_NAME
• GATEWAY_INTERFACE (CGI version)
Request-specific
• SERVER_PORT
• REQUEST_METHOD (GET, POST, etc)
• QUERY_STRING (contains GET args)
• REMOTE_HOST (domain name of client)
• REMOTE_ADDR (IP address of client)
• CONTENT_TYPE (for POST, type of data in message body, e.g.,
text/html)
• CONTENT_LENGTH (length in bytes)

class28.ppt – 14 – CS 213 S’00


Some CGI environment variables
In addition, the value of each header of type type
received from the client is placed in environment
variable HTTP_type
• Examples:
– HTTP_ACCEPT
– HTTP_HOST
– HTTP_USER_AGENT (any “-” is changed to “_”)

class28.ppt – 15 – CS 213 S’00


Serving dynamic content with GET
Question: How does the server capture the content produced by
the child?
Answer: The child writes its headers and content to stdout.
• Server maps socket descriptor to stdout (more on this later).
• Notice that only the child knows the type and size of the content. Thus the
child (not the server) must generate the corresponding headers.

/* child generates the result string */


sprintf(content, "Welcome to add.com: THE Internet addition portal\
<p>The answer is: %d + %d = %d\
<p>Thanks for visiting!\n",
n1, n2, n1+n2);

/* child generates the headers and dynamic content */


printf("Content-length: %d\n", strlen(content));
printf("Content-type: text/html\n");
printf("\r\n");
printf("%s", content);
class28.ppt – 16 – CS 213 S’00
Serving dynamic content with GET
bass> tiny 8000
HTTP request received by
GET /cgi-bin/adder?1&2 HTTP/1.1
Host: bass.cmcl.cs.cmu.edu:8000
server
<CRLF>

kittyhawk> telnet bass 8000


Trying 128.2.222.85...
Connected to BASS.CMCL.CS.CMU.EDU.
Escape character is '^]'.
GET /cgi-bin/adder?1&2 HTTP/1.1
Host: bass.cmcl.cs.cmu.edu:8000 HTTP request sent by client
<CRLF>
HTTP/1.1 200 OK HTTP response generated by
Server: Tiny Web Server the server
Content-length: 102 HTTP response generated by
Content-type: text/html
the CGI program
<CRLF>
Welcome to add.com: THE Internet addition portal.
<p>The answer is: 1 + 2 = 3
<p>Thanks for visiting!
Connection closed by foreign host.
kittyhawk>
class28.ppt – 17 – CS 213 S’00
The Tiny Web server
Tiny is a minimal Web server written in 250 lines of C.
Serves static and dynamic content with the GET method.
• text files, HTML files, GIFs, and JPGs.
• support CGI programs
Neither robust, secure, nor complete.
• It doesn’t set all of the CGI environment variables.
• Only implements GET method.
• Weak on error checking.
Interesting to study as a template for a real Web server.
Ties together many of the subjects we have studied this
semester:
• VM (mmap)
• process management (fork, wait, exec)
• network programming (sockets interface to TCP)

class28.ppt – 18 – CS 213 S’00


Tiny: cerror
cerror() returns HTML error messages to the client.
• stream is the childfd socket opened as a Unix stream so that we
can use handy routines such as fprintf and fgets instead of read
and write.

/*
* cerror - returns an error message to the client
*/
void cerror(FILE *stream, char *cause, char *errno,
char *shortmsg, char *longmsg) {
fprintf(stream, "HTTP/1.1 %s %s\n", errno, shortmsg);
fprintf(stream, "Content-type: text/html\n");
fprintf(stream, "\n");
fprintf(stream, "<html><title>Tiny Error</title>");
fprintf(stream, "<body bgcolor=""ffffff"">\n");
fprintf(stream, "%s: %s\n", errno, shortmsg);
fprintf(stream, "<p>%s: %s\n", longmsg, cause);
fprintf(stream, "<hr><em>The Tiny Web server</em>\n");
}

class28.ppt – 19 – CS 213 S’00


Tiny: main loop
Tiny loops continuously, serving client requests for
static and dynamic content.

/* open FTP listening socket */


...

while(1) {
/* wait for connection request */
/* read and parse HTTP header */
/* if request is for static content, retrieve file */
/* if request is for dynamic content, run CGI program */
}

class28.ppt – 20 – CS 213 S’00


Tiny: read HTTP
request
/* open the child socket descriptor as a stream */
if ((stream = fdopen(childfd, "r+")) == NULL)
error("ERROR on fdopen");

/* get the HTTP request line */


fgets(buf, BUFSIZE, stream);
sscanf(buf, "%s %s %s\n", method, uri, version);

/* tiny only supports the GET method */


if (strcasecmp(method, "GET")) {
cerror(stream, method, "501", "Not Implemented",
"Tiny does not implement this method");
fclose(stream);
close(childfd);
continue;
}

/* read (and ignore) the HTTP headers */


fgets(buf, BUFSIZE, stream);
while(strcmp(buf, "\r\n")) {
fgets(buf, BUFSIZE, stream);
}
class28.ppt – 21 – CS 213 S’00
Tiny: Parse the URI in the HTTP
request
/* parse the uri */
if (!strstr(uri, "cgi-bin")) { /* static content */
is_static = 1;
strcpy(cgiargs, "");
strcpy(filename, ".");
strcat(filename, uri);
if (uri[strlen(uri)-1] == '/')
strcat(filename, "index.html");
}
else { /* dynamic content: get filename and its args */
is_static = 0;
p = index(uri, '?'); /* ? separates file from args */
if (p) {
strcpy(cgiargs, p+1);
*p = '\0';
}
else {
strcpy(cgiargs, "");
}
strcpy(filename, ".");
strcat(filename, uri);
}
class28.ppt – 22 – CS 213 S’00
Tiny: access check
A real server would do extensive checking of access
permissions here.

/* make sure the file exists */


if (stat(filename, &sbuf) < 0) {
cerror(stream, filename, "404", "Not found",
"Tiny couldn't find this file");
fclose(stream);
close(childfd);
continue;
}

class28.ppt – 23 – CS 213 S’00


Tiny: serve static content
A real server would serve many more file types.
/* serve static content */
if (is_static) {
if (strstr(filename, ".html"))
strcpy(filetype, "text/html");
else if (strstr(filename, ".gif"))
strcpy(filetype, "image/gif");
else if (strstr(filename, ".jpg"))
strcpy(filetype, "image/jpg");
else
strcpy(filetype, "text/plain");

/* print response header */


fprintf(stream, "HTTP/1.1 200 OK\n");
fprintf(stream, "Server: Tiny Web Server\n");
fprintf(stream, "Content-length: %d\n", (int)sbuf.st_size);
fprintf(stream, "Content-type: %s\n", filetype);
fprintf(stream, "\r\n");
fflush(stream);
...

class28.ppt – 24 – CS 213 S’00


Tiny: serve static content (cont)
Notice the use of mmap() to copy the file that the
client requested back to the client, via the stream
associated with the child socket descriptor.

...

/* print arbitrary sized response body */


fd = open(filename, O_RDONLY);
p = mmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
fwrite(p, 1, sbuf.st_size, stream);
munmap(p, sbuf.st_size);
}

class28.ppt – 25 – CS 213 S’00


Tiny: serve dynamic content
A real server would do more complete access
checking and would initialize all of the CGI
environment variables.
/* serve dynamic content */
else {
/* make sure file is a regular executable file */
if (!(S_IFREG & sbuf.st_mode) || !(S_IXUSR & sbuf.st_mode)) {
cerror(stream, filename, "403", "Forbidden",
"You are not allow to access this item");
fclose(stream);
close(childfd);
continue;
}

/* initialize the CGI environment variables */


setenv("QUERY_STRING", cgiargs, 1);

...

class28.ppt – 26 – CS 213 S’00


Tiny: serve dynamic content (cont)
Next, the server sends as much of the HTTP
response header to the client as it can.
Only the CGI program knows the content type and
size.
Notice that we don’t mix stream (fprintf) and basic
(write) I/O. Mixed outputs don’t generally go out in
program order.
/* print first part of response header */
sprintf(buf, "HTTP/1.1 200 OK\n");
write(childfd, buf, strlen(buf));
sprintf(buf, "Server: Tiny Web Server\n");
write(childfd, buf, strlen(buf));

...

class28.ppt – 27 – CS 213 S’00


Tiny: serve dynamic content (cont)
dup2(fd1, fd2) makes descriptor fd2 to be a copy
of fd1, closing fd2 if necessary.
/* create and run the child CGI process */
pid = fork(); Notice the use
if (pid < 0) { of libc’s global
perror("ERROR in fork");
exit(1);
environ variable
} in the execve
else if (pid > 0) { /* parent */ call.
wait(&wait_status);
}
else { /* child */ The dup2 calls are
close(0); /* close stdin */ the reason that
dup2(childfd, 1); /* map socket to stdout */ the bytes that
dup2(childfd, 2); /* map socket to stderr */ the child sends to
if (execve(filename, NULL, environ) < 0) { stdout end up
perror("ERROR in execve"); back at the client.
}
}
} /* end while(1) loop */
class28.ppt – 28 – CS 213 S’00
Tiny
The complete sources sources
for the Tiny server are
available from the course Web page.
• follow the “Lectures” link.

class28.ppt – 29 – CS 213 S’00

You might also like