Chris Pollett > Students >
Ajita

    ( Print View)

    [Bio]

    [Blog]

    [C297 Proposal]

    [Deliverable 1]

    [Deliverable 2]

    [Deliverable 3]

    [Deliverable 4]

    [Presentation 1 - PDF]

    [Presentation 2 - PDF]

    [Presentation 3 - PDF]

    [Final Report 297 - PDF]

    [C298 Proposal]

Deliverable 2 - HTTP 1.1 to HTTP/2 Conversion

Deliverable 2 - Implement HTTP 1.1 to HTTP/2 Conversion

Description: Implement a program that takes in an HTTP 1.1 request and converts it into HTTP/2 binary format. This program will give an understanding of how request conversion happens. The program works in 3 parts:

  1. Converting the format of an HTTP message into HTTP/2 frames by adding the HTTP/2 headers and assigning their values and re-adjusting the previous values.
  2. The converted request is still in human-readable language. It can then be converted to binary according to the HTTP/2 defined standards.
  3. Conversion of each frame to binary and hexadecimal since hex is easier to understand and work with.

Example:

        GET /doc/test.html HTTP/1.1
Host: www.test101.com
Accept: image/gif, image/jpeg, */*
Content-Length: 35

Converts to :

[Frame 1] => 00 00 87 01 20 00 00 49 FF EB 6E 5E 9A 37 E4 83 D8 23 C5 A9 5D 73 C7 A3 2E DC B0 7B 04 8A 95 28 5F 8D D8 D7 5C 30 F4 D1 07 B0 5F 93 7E 3B FA 65 E7 D2 ED 1D 36 EC A9 1B F9 F4 83 D8 3B F7 EF 77 4C BC FA 63 86 37 63 DF B6 A0 E3 C7 97 87 48 3D 83 4E DC 39 F2 DF 9F 4E 6B 20 D3 B7 0E 7C B7 EA E1 97 3D 90 55 7D 55 0F 7E EE 99 77 74 B6 66 5D D9 FA 68 83 D8 33 D6 02
[Frame 2] => 00 00 20 00 A0 00 00 49 FF C5 BF 7E B9 39 3D C7 2C F4 D6 6C 3D 7A 68 DF CB DE 18 7A EC DF 5C 3D F9 74 6C 6F

Step-1: Parse the request

This is done by extracting all the parts of the request ('method', 'path', 'protocol', 'headers', 'body') and replacing them with the appropriate new format.

The first function parses the request to extract out all parts and creates an array as follows:

parseH1Request($request_string)

returns:

array( 'method' => $method, 'path' => $path, 'protocol' => $protocol, 'headers' => $headers, 'body' => $body );

Step-2: Setup frame creation configuration

In this step, the initial flags are set according to the parts of the request. The number and types of frames to be created are also decided within this function. Each frame to be created is then done by calling its respective function and passing the necessary config.

Eg: a GET request with a body => 2 frames: Header (with end_header flag set) and data (with end_stream flag set)

createFrames($request_array)

Step-3: Creating HEADERS frame

According to the new format, a request contains a certain number of headers with binary values assigned to them. These headers include packet type, stream identifier number, flags for priority, padding, etc. These headers are added to the existing HTTP headers, and a frame is created for them in the function:

createHeadersFrame($request_array, $END_STREAM_FLAG, $END_HEADERS_FLAG)

returns:


        [headerFrame] => Array
        (
            [length] => 135
            [type] => 0x1
            [flags] => Array
                (
                    [end_stream_flag] => 0
                    [end_header_flag] => 1
                    [padded_flag] => 0
                    [prior_flag] => 0
                )

            [R] => 0
            [streamID] => 18943
            [padLength] => not set
            [E] => not set
            [StreamDepenedency] => not set
            [weight] => not set
            [requestHeaders] => :method = GET
                                :scheme = HTTP/1.1
                                :path = /doc/test.html
                                Host = www.test101.com
                                Accept = image/gif, image/jpeg, */*
                                Content-Length = 35

            [padding] => not set
        )

    

Step-4: Creating DATA frame

Since the example request had a body as well, the createDataFrame() is also triggered in step 2. This focuses on creating the frame format of the data frame and adds the body of the original request as this frame's payload.

createDataFrame($request_array, $END_STREAM_FLAG, $END_HEADERS_FLAG)

returns:


        [dataFrame] => Array
        (
            [length] => 32
            [type] => 0x0
            [flags] => Array
                (
                    [end_stream_flag] => 1
                    [end_header_flag] => 1
                    [padded_flag] => 0
                    [prior_flag] => 0
                )

            [R] => 0
            [streamID] => 18943
            [padLength] => not set
            [data] => bookId=12345&author=paulo+Coehlo
            [padding] => not set
        )
    

NOTE: The fields in frames with value as “not set” are fields that are not mandatory. And according to the example get request we are following in this document, they are not required. These fields are ignored when converting to binary.

Step-5: Convert to Binary

The function convertFrameToBin($http2_frames) receives an array of frames as input. Within this function, each frame is iterated over, and its components are converted to binary format following the specifications outlined in the RFC. Binary values are assigned to the headers; for instance, the 'type' header may range from 0x0 to 0x9 based on the frame type. The field values of each header are then extracted and passed to respective functions responsible for converting them into binary values. These binary values are concatenated into a string. For instance, the function getTypeInBinary($type) handles the conversion process as outlined in the table below:

DATA Value
HEADERS 0x1
PRIORITY 0x2
RST_STREAM 0x3
SETTINGS 0x4
PUSH_PROMISE 0x5
PING 0x6
GOAWAY 0x7
WINDOW_UPDATE 0x8
CONTINUATION 0x9
convertFrameToBin($http2_frames)

returns:


    Array
(
    [0] => 
00000000 00000000 10000111 00000001 00100000 00000000 00000000 00000000 10010011 11111111 11110101 10110110 11011100 10111110 10011010 10001101
11111110 01000001 11110110 00001000 11110001 01101010 10010101 11010111 00111100 01111000 01111010 11101110 00101110 01111111 01100001 10111010
11000110 10101110 11011110 01101100 11101000 11011110 01110111 10100000 00110101 01001101 11111101 01111010 01000100 00011110 11011000 00011011
10111111 11101011 10101000 01111010 11010001 01111011 11111011 11111111 01101101 01000000 01110001 11000111 10000111 01110110 00111000 00101100
11011110 01111101 11110110 11011010 01000000 01111011 11111011 11101111 10111011 10111010 01001101 11000110 01011110 01111000 01011110 11111101
01100101 11100111 10100100 01110001 11000111 01101111 01111101 10110101 10100000 01110001 11110000 11110001 11100101 11110000 01110100 10000001
11110110 00000110 10011110 01101101 11100000 01110011 11100101 10111111 11001111 11001011 01111000 11101010 11111101 01110101 01011100 00011001
11101100 11101100 10010101 10101110 11011001 11111010 10011010 00010000 00000111 11011000 00000110 00111101 11010110



    [1] => 
00000000 00000000 00100000 00000000 00000000 10100000 00000000 00000000 10010011 11111111 10001011 01101111 11011111 01111101 01011100 10011100 
10011110 11101011 10011011 10001110 01011100 11111001 01101000 01101111 11111001 01111011 11110001 11100101 11011110 01101100 11110101 11011111 
10100110 11101000 01111011 11110111 00101110 10001101 01100100 11101110 01101110 10111100 00111101 11111101 01010111 00011011 00110111 11100111

)
    

Step-6: Converting to Hexadecimal

Converting to hex is done by chunking the entire binary string into chunks of 8 bits each. These chunks are passed into a prebuilt function that converts binary to hex.

binToHex($arr)

returns:


        Array
        (
            [Frame 1] =>  00 00 87 01 20 00 00 49 FF EB 6E 5E 9A 37 E4 83 D8 23 C5 A9 5D 73 C7 A3 2E DC B0 7B 04 8A
                          95 28 5F 8D D8 D7 5C 30 F4 D1 07 B0 5F 93 7E 3B FA 65 E7 D2 ED 1D 36 EC A9 1B F9 F4 83 D8 
                          3B F7 EF 77 4C BC FA 63 86 37 63 DF B6 A0 E3 C7 97 87 48 3D 83 4E DC 39 F2 DF 9F 4E 6B 20 
                          D3 B7 0E 7C B7 EA E1 97 3D 90 55 7D 55 0F 7E EE 99 77 74 B6 66 5D D9 FA 68 83 D8 33 D6 02

            [Frame 2] =>  00 00 20 00 A0 00 00 49 FF C5 BF 7E B9 39 3D C7 2C F4 D6 6C 3D 7A 68 DF CB DE 18 7A EC DF 
                          5C 3D F9 74 6C 6F
        )
        
    

Results

Result Page Screenshot Result Page Screenshot Result Page Screenshot Result Page Screenshot

Find the full code below:

parser.php.zip