CGI1.HTTP/TCP Server2.HTTP Client3.CGI server(HTTP/TCP server) and CGI application 2.HTTP Client 3.CGI server(HTTP/TCP server) and CGI application

CGI(Common Gateway Interface)

This article’s snippets are python codes.

The core technology for CGI is “the mechanism of communicating from client to server”.CGI 技术的核心是“客户端向服务器传递信息的机制”

[code 1]HTTP/TCP server for receiving message from HTTP client,such as browser.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import socket
HOST = '0.0.0.0'
PORT = 80
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0,
                              socket.AI_PASSIVE):
    af, sock_type, proto, _, sa = res
    s = socket.socket(af, sock_type, proto)
    s.bind(sa)
    s.listen(1)
    break
conn, _ = s.accept()
data = conn.recv(1024)
print data
conn.close()

type http://localhost/path/to/me?param=123 into browser,the output of code 1 will be

[output 1]

GET /path/to/me?param=123 HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8

[code 2]We add response to our code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import socket
HOST = '0.0.0.0'
PORT = 80
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM, 0,
                              socket.AI_PASSIVE):
    af, sock_type, proto, _, sa = res
    s = socket.socket(af, sock_type, proto)
    s.bind(sa)
    s.listen(1)
    break
conn, _ = s.accept()
data = conn.recv(1024)
print data
conn.send("<html>hello world</html>")
conn.close()

type http://localhost into browser, we’ll say hello world in browser.

2.HTTP Client

We copy output 1 as inputs of our [code 3]HTTP Client

[code 3]HTTP Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import socket
HOST = '127.0.0.1'
PORT = 80
HEAD = """
GET /path/to/me?param=123 HTTP/1.1
Host: localhost
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: zh-CN,zh;q=0.8
"""
s = None
for res in socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_STREAM):
    af, sock_type, proto, _, sa = res
    s = socket.socket(af, sock_type, proto)
    s.connect(sa)
    break
s.send(HEAD)
data = s.recv(1024)
while data:
    print data
    data = s.recv(1024)
s.close()

Run code 2 ,then run code 3, we’ll see the output 2:

[output 2]

1
<html>hello world</html>

3.CGI server(HTTP/TCP server) and CGI application

The CGI server processes all of the client’s requests is not realistic usually.Note that, in real life, our CGI server sends the client’s requests to CGI applications, then return CGI applications’ results to the client.

 +-----------+   1  +------------+   2   +-----------------+
 |           | ===> |            | ====> |                 |
 |  clients  |      | CGI server |       | CGI application |
 |           |   4  |            |   3   |                 |      
 +-----------+ <=== +------------+ <==== +-----------------+

In the previous article, we have simulated the transformation of static web pages by HTTP/TCP.
Now we’ll see how CGI Server communication with CGI application.
cgi-1
cgi-2

[code 4] CGI server cgiserver.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import sys
import os
class TMyOut(object):
    def __init__(self):
        self.__s = ""
    def write(self, s):
        self.__s += s
    def readall(self):
        return self.__s
# save stdout
save_stdout = sys.stdout
# use environment variables to send message to `cgi applications`
env = {"A1": "Hello", "A2": "world"}
os.environ.update(env)
# redirect stdout to our out,so that `cgi applications` can send message to `cgi server` by stdout
my_out = TMyOut()
sys.stdout = my_out
# execute `cgi application`
execfile("cgi_application.py")
# recover stdout
sys.stdout = save_stdout
print "my out : " + my_out.readall()

[code 5] CGI application cgi_application.py

1
2
3
import os
s = os.environ["A1"] + " " + os.environ["A2"] + "!"
print s

the output will be my out : Hello world!

[reference]

1.沈著初级CGI:原理