An Adventure Story
Request
Response
1991 - HTTP 0.9
Hypertext Transfer Protocol -- HTTP/0.9 (http://www.w3.org/Protocols/HTTP/AsImplemented.html)
May 1996 - HTTP 1.0
Hypertext Transfer Protocol -- HTTP/1.0 (http://tools.ietf.org/html/rfc1945)
June 1999 - HTTP 1.1
Hypertext Transfer Protocol -- HTTP/1.1 (http://tools.ietf.org/html/rfc2616)
June 2014 - HTTP 1.1, you know, for clarity
Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing (http://tools.ietf.org/html/rfc7230)
Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content (http://tools.ietf.org/html/rfc7231)
Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests (http://tools.ietf.org/html/rfc7232)
Hypertext Transfer Protocol (HTTP/1.1): Range Requests (http://tools.ietf.org/html/rfc7233)
Hypertext Transfer Protocol (HTTP/1.1): Caching (http://tools.ietf.org/html/rfc7234)
Hypertext Transfer Protocol (HTTP/1.1): Authentication (http://tools.ietf.org/html/rfc7235)
May 2015 - HTTP 2.0, SPDY made standard
Hypertext Transfer Protocol Version 2 (HTTP/2) (http://tools.ietf.org/html/rfc7540)
$ telnet localhost 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET /path/to/resource HTTP/1.0
HTTP/1.1 200 OK
Server: nginx/1.8.0
Date: Tue, 02 Jun 2015 22:42:54 GMT
Content-Type: text/html
Content-Length: 12
Last-Modified: Tue, 02 Jun 2015 22:37:02 GMT
Connection: close
ETag: "556e300e-c"
Accept-Ranges: bytes
Hello World
Connection closed by foreign host.
Ubuntu Install
$ sudo apt-get install nginx
Mac Install
$ brew install nginx
Windows Install
$ lol
worker_processes 1;
events {
worker_connections 1024;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
include mime.types;
default_type application/octet-stream;
##
# Logging Settings
##
access_log /Users/crempp/projects/ngw2f/nginx/logs/access.log;
error_log /Users/crempp/projects/ngw2f/nginx/logs/error.log;
##
# Gzip Settings
##
gzip on;
gzip_disable "msie6";
server {
listen 8080 default_server;
listen [::]:8080 default_server ipv6only=on;
root /Users/crempp/projects/ngw2f/nginx/html;
index index.html index.htm;
# Make site accessible from http://localhost/
server_name localhost;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html;
# Uncomment to enable naxsi on this location
# include /etc/nginx/naxsi.rules
}
}
}
include servers/*;
def app(environ, start_response):
"""Simplest possible WSGI application object"""
data = 'Hello, World! (from Gunicorn)\n'
status = '200 OK'
response_headers = [
('Content-type','text/plain'),
('Content-Length', str(len(data)))
]
start_response(status, response_headers)
return iter([data])
$ virtualenv env
$ source env/bin/activate
(env)$ pip install gunicorn
$ gunicorn --workers=2 app:app
$ gunicorn --workers=2 app:app
PEP 333 / PEP 3333
Must provide environ, a dictionary of environment variables
Must provide start_response(status, headers), a callable accepting two positional arguments
WSGI Server Requirements
WSGI App Requirements
Must provide app(environ, start_response), a callable accepting two positional argument
iterable = application(environ, start_response)
for data in iterable:
# send data to client
def application(environ, start_response):
status = '200 OK'
response_headers = []
# Tell server about the response
start_response(status, response_headers)
# Return body content
return ['Body content']
def middleware(environ, start_response):
# Do stuff to environ
# Choose application to handle request
response_iter = application(environ, start_response)
# Do stuff to response
return response_iter
from werkzeug.wrappers import Request, Response
def application(environ, start_response):
request = Request(environ)
text = 'Hello %s!' % request.args.get('name', 'World')
response = Response(text, mimetype='text/plain')
return response(environ, start_response)
from werkzeug.wrappers import Request, Response
@Request.application
def application(request):
result = ['Hello World']
return Response(result, mimetype='text/html')
or
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World (from Flask)"
if __name__ == "__main__":
app.run()
If any of this interests you visit