• Stars
    star
    338
  • Rank 120,881 (Top 3 %)
  • Language
    Common Lisp
  • Created over 9 years ago
  • Updated 6 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

A fast HTTP request/response parser for Common Lisp.

fast-http

Build Status

This is a fast HTTP request/response protocol parser for Common Lisp.

Features

  • Parses both HTTP requests and responses.
  • Handles persistent streams (keep-alive).
  • Decodes chunked encoding.
  • Exports low-level APIs which don't any memory allocations during parsing.

API differences from http-parse

The API is quite similar to http-parse, although there's some differences.

  • http, http-request and http-response are structure classes, not standard classes.
  • http doesn't have :force-stream option. (always streaming)
  • http doesn't have :store-body option because it can consume much memory.
  • body-callback for make-parser doesn't take a flag body-complete-p.
    • Use finish-callback to know if the parsing is finished.
  • body-callback for make-parser takes pointers start and end.
  • multipart-callback for make-parser has been deleted.
    • Use make-multipart-parser and body-callback by yourself.
  • :callback of make-multipart-parser takes a stream, not a body octet vector at the 4th argument.
  • Raises errors aggressively while parsing.
    • Handle fast-http-error as you needed.
  • Doesn't use a property list as a representation of HTTP headers. (See issue #1)

APIs

[Structure] http

Base structure class extended by http-request and http-response.

NOTE: Don't use this class directly unless you're intended to use low-level APIs of fast-http.

(make-http)
;=> #S(FAST-HTTP.HTTP:HTTP
;     :METHOD NIL
;     :MAJOR-VERSION 0
;     :MINOR-VERSION 9
;     :STATUS 0
;     :CONTENT-LENGTH NIL
;     :CHUNKED-P NIL
;     :UPGRADE-P NIL
;     :HEADERS NIL
;     :HEADER-READ 0
;     :MARK -1
;     :STATE 0)

Methods

  • http-method: Returns a HTTP request method in a keyword (such like :GET, :POST or :HEAD).
  • http-major-version: Returns a HTTP protocol major version in an integer (such like 1 or 0).
  • http-minor-version: Returns a HTTP protocol minor version in an integer (such like 1 or 0).
  • http-version: Returns a HTTP protocol version in a float (such like 1.0 or 1.1).
  • http-status: Returns a HTTP response status code in an integer (such like 200 or 302).
  • http-content-length: Returns a value of Content-Length header in an integer. If the header doesn't exist, it returns NIL.
  • http-chunked-p: Returns T if the value of Transfer-Encoding header is chunked. If the header doesn't exist, it returns NIL.
  • http-upgrade-p: Returns T if Upgrade header exists.
  • http-headers: Returns a hash-table which represents HTTP headers. Note all hash keys are lower-cased and all values are string except Set-Cookie header, whose value is a list of strings. (Content-Length -> "content-length").

[Structure] http-request (extends http)

Structure class holds values specific to an HTTP request.

(make-http-request)
;=> #S(FAST-HTTP.HTTP:HTTP-REQUEST
;     :METHOD NIL
;     :MAJOR-VERSION 0
;     :MINOR-VERSION 9
;     :STATUS 0
;     :CONTENT-LENGTH NIL
;     :CHUNKED-P NIL
;     :UPGRADE-P NIL
;     :HEADERS NIL
;     :HEADER-READ 0
;     :MARK -1
;     :STATE 0
;     :RESOURCE NIL)

Methods

  • http-resource: Returns an URI string.

[Structure] http-response (extends http)

Structure class holds values specific to an HTTP response.

(make-http-response)
;=> #S(FAST-HTTP.HTTP:HTTP-RESPONSE
;     :METHOD NIL
;     :MAJOR-VERSION 0
;     :MINOR-VERSION 9
;     :STATUS 0
;     :CONTENT-LENGTH NIL
;     :CHUNKED-P NIL
;     :UPGRADE-P NIL
;     :HEADERS NIL
;     :HEADER-READ 0
;     :MARK -1
;     :STATE 0
;     :STATUS-TEXT NIL)

Methods

  • http-status-text: Returns an response status text (such like Continue, OK or Bad Request).

[Function] make-parser (http &key first-line-callback header-callback body-callback finish-callback)

Makes a parser closure and returns it.

(let ((http (make-http-request)))
  (make-parser http
               :body-callback
               (lambda (data start end)
                 (write-to-buffer data start end))
               :finish-callback
               (lambda ()
                 (handle-response http))))
;=> #<CLOSURE (LAMBDA (DATA &KEY (START 0) END)
;              :IN
;              FAST-HTTP.PARSER:MAKE-PARSER) {10090BDD0B}>

The closure takes one required argument data, that is a simple byte vector and two keyword arguments start and end.

Callbacks

  • first-line-callback (): This callback function will be called when the first line is parsed.
  • header-callback (headers-hash-table): This callback function will be called when the header lines are parsed. This function is the same object to the http object holds.
  • body-callback (data-byte-vector): This callback function will be called whenever it gets a chunk of HTTP body. Which means this can be called multiple times.
  • finish-callback (): This callback function will be called when the HTTP message ends.

NOTE: If the HTTP request/response has multiple messages (like HTTP/1.1 pipelining), all these functions can be called multiple times.

[Function] make-multipart-parser (content-type callback)

Makes a multipart/form-data parser closure and returns it.

This takes 2 arguments, content-type (such like "multipart/form-data; boundary=--AsB03x") and callback. The callback is a function which takes exact 4 arguments -- a field name, field headers, field meta data and body bytes.

Low-level APIs

The following functions are intended to be used for internally. These APIs are likely to change in the future.

Most of functions are declared as (optimize (speed 3) (safety 0)) which means it won't check the type of arguments.

[Structure] callbacks

Structure class holds callback functions. The callbacks are similar to make-parser's, but don't correspond to them directly.

Slots

  • message-begin (http): This will be called when a new HTTP message begins.
  • url (http data start end): This will be called when an URL part of the HTTP request parsed.
  • first-line (http): This will be called when the first line of the HTTP request/response parsed.
  • status (http data start end): This will be called when the status text (not code) of the HTTP response parsed.
  • header-field (http data start end): This will be called when a header field parsed.
  • header-value (http data start end): This will be called when a header value parsed. This function can be called multiple times when the header value is folded onto multiple lines.
  • headers-complete (http): This will be called when all headers parsed.
  • body (http data start end): This will be called whenever the parser gets a chunk of HTTP body.
  • message-complete (http): This will be called when the HTTP message ends.

[Function] parse-request (http callbacks data &key (start 0) end)

Parses data as an HTTP request, sets values to http and invokes callbacks in callbacks.

This takes a http object, a callbacks object, and a simple byte vector data and two pointers -- start and end. If end is nil, the length of data will be used.

[Function] parse-response (http callbacks data &key (start 0) end)

Parses data as an HTTP response, sets values to http and invokes callbacks in callbacks.

Takes a http object, a callbacks object, and a simple byte vector data and two pointers -- start and end. If end is nil, the length of data will be used.

[Condition] eof

Will be raised when the data ends in the middle of parsing.

Installation

(ql:quickload :fast-http)

Running tests

(asdf:test-system :fast-http)

Benchmark

  • Parsing an HTTP request header 100000 times.

In this benchmark, fast-http is 1.25 times faster than http-parser, a C equivalent.

http-parser (C) fast-http
0.108s 0.086s

Environment

  • Travis CI
  • SBCL 1.2.6

You can see the latest result at Travis CI.

fast-http (Common Lisp)

(ql:quickload :fast-http-test)
(fast-http-test.benchmark:run-ll-benchmark)
Evaluation took:
  0.086 seconds of real time
  0.085897 seconds of total run time (0.084763 user, 0.001134 system)
  100.00% CPU
  257,140,751 processor cycles
  0 bytes consed

http-parser (C)

#include "http_parser.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <time.h>

static http_parser *parser;

static http_parser_settings settings_null =
  {.on_message_begin = 0
  ,.on_header_field = 0
  ,.on_header_value = 0
  ,.on_url = 0
  ,.on_status = 0
  ,.on_body = 0
  ,.on_headers_complete = 0
  ,.on_message_complete = 0
  };

int
main (void)
{
  const char *buf;
  int i;
  float start, end;
  size_t parsed;

  parser = malloc(sizeof(http_parser));

  buf = "GET /cookies HTTP/1.1\r\nHost: 127.0.0.1:8090\r\nConnection: keep-alive\r\nCache-Control: max-age=0\r\nAccept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.56 Safari/537.17\r\nAccept-Encoding: gzip,deflate,sdch\r\nAccept-Language: en-US,en;q=0.8\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\nCookie: name=wookie\r\n\r\n";

  start = (float)clock()/CLOCKS_PER_SEC;
  for (i = 0; i < 100000; i++) {
    http_parser_init(parser, HTTP_REQUEST);
    parsed = http_parser_execute(parser, &settings_null, buf, strlen(buf));
  }
  end = (float)clock()/CLOCKS_PER_SEC;

  free(parser);
  parser = NULL;

  printf("Elapsed %f seconds.\n", (end - start));

  return 0;
}
$ make http_parser.o
$ gcc -Wall -Wextra -Werror -Wno-error=unused-but-set-variable -O3 http_parser.o mybench.c -o mybench
$ mybench
Elapsed 0.108815 seconds.

Author

Copyright

Copyright (c) 2014 Eitaro Fukamachi

License

Licensed under the MIT License.

More Repositories

1

woo

A fast non-blocking HTTP server on top of libev
Common Lisp
1,255
star
2

clack

Web server abstraction layer for Common Lisp
Common Lisp
1,021
star
3

caveman

Lightweight web application framework for Common Lisp.
Common Lisp
769
star
4

qlot

A project-local library installer for Common Lisp
Common Lisp
384
star
5

dexador

A fast HTTP client for Common Lisp
Common Lisp
358
star
6

sxql

An SQL generator for Common Lisp.
Common Lisp
349
star
7

mito

An ORM for Common Lisp with migrations, relationships and PostgreSQL support
Common Lisp
270
star
8

ningle

Super micro framework for Common Lisp
Common Lisp
254
star
9

cl-project

Generate modern project skeletons
Common Lisp
234
star
10

prove

Yet another unit testing framework for Common Lisp
Common Lisp
217
star
11

cl-dbi

Database independent interface for Common Lisp
Common Lisp
195
star
12

rove

#1=(yet another . #1#) common lisp testing library
Common Lisp
139
star
13

lack

Lack, the core of Clack
Common Lisp
137
star
14

quri

Yet another URI library for Common Lisp
Common Lisp
105
star
15

websocket-driver

WebSocket server/client implementation for Common Lisp
Common Lisp
101
star
16

datafly

A lightweight database library for Common Lisp.
Common Lisp
97
star
17

utopian

A web framework for Common Lisp never finished.
Common Lisp
95
star
18

lsx

Embeddable HTML templating engine for Common Lisp with JSX-like syntax
Common Lisp
78
star
19

shelly

[OBSOLETE] Use Roswell instead.
Common Lisp
63
star
20

envy

Configuration switcher by an environment variable inspired by Config::ENV.
Common Lisp
57
star
21

integral

[OBSOLETE] Use Mito instead.
Common Lisp
54
star
22

mondo

Simple Common Lisp REPL
Common Lisp
52
star
23

psychiq

Background job processing for Common Lisp
Common Lisp
51
star
24

getac

Quick unit testing tool for competitive programming
Common Lisp
46
star
25

dockerfiles

Dockerfiles for Common Lisp programming
Shell
40
star
26

proc-parse

Procedural vector parser
Common Lisp
36
star
27

jose

A JOSE implementation
Common Lisp
32
star
28

redmine-el

See Redmine on Emacs
Emacs Lisp
30
star
29

legion

Simple multithreading worker mechanism.
Common Lisp
30
star
30

cl-coveralls

Common Lisp
29
star
31

docker-cl-example

Example projects to run/develop Common Lisp web application on Docker container
Common Lisp
28
star
32

L5

Yet Another Presentation Tool for Lispers
Clojure
28
star
33

event-emitter

Event mechanism for Common Lisp objects.
Common Lisp
28
star
34

.lem

Lem configuration files
Common Lisp
27
star
35

assoc-utils

Utilities for manipulating association lists.
Common Lisp
25
star
36

clozure-cl

Unofficial mirror of Clozure CL
Common Lisp
25
star
37

supertrace

Superior Common Lisp `trace` functionality for debugging/profiling real world applications.
Common Lisp
25
star
38

myway

Sinatra-compatible URL routing library for Common Lisp
Common Lisp
24
star
39

fast-websocket

Optimized low-level WebSocket protocol parser written in Common Lisp
Common Lisp
22
star
40

uncl

Un-Common Lisp on Common Lisp
Common Lisp
22
star
41

cl-locale

Simple i18n library for Common Lisp
Common Lisp
21
star
42

ragno

Common Lisp Web crawling library based on Psychiq.
Common Lisp
19
star
43

safety-params

Check params
Common Lisp
19
star
44

anypool

General-purpose connection pooling library for Common Lisp
Common Lisp
19
star
45

mito-auth

User authorization for Mito classes.
Common Lisp
18
star
46

cl-cookie

HTTP cookie manager
Common Lisp
18
star
47

xsubseq

Efficient way to use "subseq"s in Common Lisp
Common Lisp
16
star
48

smart-buffer

Smart octets buffer.
Common Lisp
16
star
49

http-body

HTTP POST data parser.
Common Lisp
15
star
50

re21

CL21's spin-off project that provides neat APIs for regular expressions.
Common Lisp
15
star
51

webapi

CLOS-based wrapper builder for Web APIs.
Common Lisp
15
star
52

lev

libev bindings for Common Lisp
Common Lisp
15
star
53

.emacs.d

My .emacs.d
Emacs Lisp
15
star
54

lesque

[OBSOLETE] Use Psychiq instead.
Common Lisp
14
star
55

pem

PEM parser.
Common Lisp
14
star
56

circular-streams

Circularly readable streams for Common Lisp.
Common Lisp
14
star
57

mito-attachment

Mito mixin class for file management outside of RDBMS
Common Lisp
14
star
58

emacs-config

[OBSOLETE] More simplified version is
Emacs Lisp
13
star
59

yapool

A Common Lisp command-line tool for executing shell commands via SSH.
12
star
60

cl-line-bot-sdk

SDK for the LINE Messaging API for Common Lisp
Common Lisp
11
star
61

id3v2

ID3v2 parser
Common Lisp
10
star
62

kindly-mode

Amazon Kindle-like view mode for Emacs.
Emacs Lisp
10
star
63

wsock

Low-level UNIX socket library
Common Lisp
9
star
64

asn1

ASN.1 decoder
Common Lisp
9
star
65

can

A role-based access right control library.
Common Lisp
8
star
66

hatenablog-theme-writer

็‰ฉๆ›ธใใฎใŸใ‚ใฎใƒ–ใƒญใ‚ฐใƒ†ใƒผใƒžใ€ŒWriterใ€ for ใฏใฆใชใƒ–ใƒญใ‚ฐ
CSS
7
star
67

neovim-config

~/.config/nvim
Vim Script
7
star
68

clee

Common Lisp Event Engine
Common Lisp
6
star
69

fukacl

Fukamachi Common Lisp Package
Common Lisp
6
star
70

ponzu.db

O/R Mapper, a part of Ponzu Framework, for Common Lisp
Common Lisp
6
star
71

gotanda

Common Lisp
6
star
72

clbuild

Unofficial fork of clbuild
Shell
5
star
73

mp3-duration

Get the duration of an MP3 file
Common Lisp
5
star
74

asdf-c-test-file

Provides ASDF component :test-file.
Common Lisp
5
star
75

sxql-abstract

An abstraction layer for SQL between RDBMS.
Common Lisp
5
star
76

as-interval

An extension of cl-async for introducing 'interval' feature.
Common Lisp
5
star
77

fukamachi.github.com

HTML
4
star
78

p5-shelly

[DEPRECATED] Moved to https://github.com/fukamachi/shelly
Perl
4
star
79

github-webhook

Docker container to listen for GitHub webhook events
Common Lisp
4
star
80

dont-type-twice-el

Supports your effective text editing.
Emacs Lisp
4
star
81

nail

Common Lisp
4
star
82

lem-vi-sexp

vim-sexp port for Lem
Common Lisp
4
star
83

multival-plist

Property List stores multiple values per one key.
Common Lisp
4
star
84

kunitada-bot

All tweets should be "fastest".
Ruby
3
star
85

trivial-utf-8

Imported from the original darcs repo.
Common Lisp
3
star
86

closure-library-skeleton

Skeleton files for a project using Google Closure Library.
JavaScript
3
star
87

clack-doc

[DEPRECATED] Documentation tool for Clack (I moved them to Quickdocs.org)
Common Lisp
3
star
88

ac-swift

Swift auto completion for Emacs
Emacs Lisp
3
star
89

gotumda

Put all your tasks into one bucket.
JavaScript
3
star
90

opImKayacComPlugin

PHP
2
star
91

partial-bench

A tiny benchmarking library to get a running time of a specific part.
Common Lisp
2
star
92

p5-gotumda

Communicate over tasks.
JavaScript
2
star
93

swank.ros

Common Lisp
2
star
94

Plack-Middleware-Try

Plack Middleware to catch exceptions.
Perl
2
star
95

roswell

intend to be a lisp installer and launcher for major environment that just work.
C
2
star
96

Plack-Middleware-StackTraceLog

Plack Middleware for logging when your app dies.
Perl
1
star
97

cl-weather-jp

Get weather in Japan
Common Lisp
1
star
98

rove-test-example

Common Lisp
1
star