Skip to content
This repository was archived by the owner on Nov 8, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 62 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The only glitch is that cURL `--trace` saves data in [its custom format][gist],
$ curl --trace - http://httpbin.org/ip | curl-trace-parser
```

## Example
## Sample API

We will be using this [sample API][apiarydoc] created with the [Apiary.io mock server](http://apiary.io) to demonstrate tracing an HTTP communication and the use of the cURL trace parser.

Expand All @@ -45,51 +45,89 @@ Note this cURL example is copied and pasted from [Apiary interactive API documen

[example]: http://docs.curltraceparser.apiary.io/#get-%2Fshopping-cart

## Parse the trace file from command line
## Examples

### `--raw` format

The output is ASCII representation of a raw [HTTP message][message] with few modifications:

- Request line begins with `> `
- Response line begins with `< `
- Request and Response is delimited by CR+LF
- Both Request and Response are terminated by an extra trailing LF

Note: This is little bit tricky because HTTP RFC does not have declared delimiter for Request and Response, for obvious reasons.

```bash
$ cat tracefile | curl-trace-parser
> GET /shopping-cart HTTP/1.1
$ cat tracefile | curl-trace-parser --raw
> POST /shopping-cart HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5
> Host: curltraceparser.apiary.io
> Accept: */*
>
> Content-Type: application/json
> Content-Length: 39
>
> { "product":"1AB23ORM", "quantity": 2 }

< HTTP/1.1 200 OK
< HTTP/1.1 201 Created
< Content-Type: application/json
< Date: Sun, 21 Jul 2013 13:23:55 GMT
< Date: Tue, 30 Jul 2013 11:32:30 GMT
< X-Apiary-Ratelimit-Limit: 120
< X-Apiary-Ratelimit-Remaining: 119
< Content-Length: 119
< Content-Length: 50
< Connection: keep-alive
<
< { "items": [
< { "url": "/shopping-cart/1", "product":"2ZY48XPZ", "quantity": 1, "name": "New socks", "price": 1.25 }
< ] }
< { "status": "created", "url": "/shopping-cart/2" }
```

### `--blueprint` format

The output is HTTP Request and Response in the [API blueprint format](http://apiblueprint.org) which is the superset of markdown.

```
$ cat tracefile | ./bin/curl-trace-parser --blueprint
# POST /shopping-cart
+ Request
+ Headers

User-Agent:curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5
Host:curltraceparser.apiary.io
Accept:*/*
Content-Type:application/json
Content-Length:39

+ Body

{ "product":"1AB23ORM", "quantity": 2 }

+ Response 201
+ Headers

Content-Type:application/json
Date:Tue, 30 Jul 2013 11:32:30 GMT
X-Apiary-Ratelimit-Limit:120
X-Apiary-Ratelimit-Remaining:119
Content-Length:50
Connection:keep-alive

+ Body

{ "status": "created", "url": "/shopping-cart/2" }

```

## Parse the trace file using Node.JS
Note: This format does not expect any CR+LF in body

### Parse the trace to raw HTTP file using Node.JS

```javascript
var fs = require('fs');
var parser = require('curl-trace-parser');
fs.readFile('./tracefile', 'utf8', function (err,trace) {
console.log(parser.parseToString(trace));
console.log(parser.parse(trace));
})
```

## Output format

The output is ASCII representation of a raw [HTTP message][message] with few modifications:

- Request line begins with `> `
- Response line begins with `< `
- Request and response is delimited by CR+LF
- Both Request and Response are terminated by an extra trailing LF

Note: This is little bit tricky because HTTP RFC does not have declared delimiter for Request and Response, for obvious reasons.

## Output format reverse parser

```javascript
Expand Down
30 changes: 26 additions & 4 deletions bin/curl-trace-parser
Original file line number Diff line number Diff line change
@@ -1,21 +1,43 @@
#!/usr/bin/env node

var cmd = require('commander');
var parser = require('../lib/parser');
cmd.version('0.0.1');
var curl = require('../lib/parser');
var http = require('http-string-parser');
var bf = require('api-blueprint-http-formatter')

var stdin = "";

process.stdin.resume();
process.stdin.setEncoding('utf8');

cmd.command('curl-trace-parser')
.description('Parse output form curl --trace option')
.version('0.0.8')
.option('-r, --raw', 'Output raw data (Default)')
.option('-b, --blueprint', 'Output in API blueprint format')
.parse(process.argv);

process.stdin.on('data', function(data) {
stdin += data;
});

process.stdin.on('end', function() {
parserOutput = parser.parseToString(stdin)
process.stdout.write(parserOutput);
//TODO commander options does not work here :(
var option = process.argv[2];

if(option == '-r' || option == '--raw' || option == undefined){
var parserOutput = curl.parseToString(stdin);
process.stdout.write(parserOutput);
}
if(option == 'b' || option == '--blueprint'){
var rawPair = curl.parse(stdin);
parsedPair = {
'request': http.parseRequest(rawPair['request']),
'response': http.parseResponse(rawPair['response'])
}
var blueprint = bf.format(parsedPair);
process.stdout.write(blueprint);
}
process.exit(0)
});

Expand Down
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "curl-trace-parser",
"version": "0.0.7",
"version": "0.0.8",
"description": "Parse curl --trace option output to raw HTTP message",
"main": "lib/parser.js",
"scripts": {
Expand All @@ -11,7 +11,9 @@
"curl-trace-parser": "bin/curl-trace-parser"
},
"dependencies": {
"commander": "1.2.0"
"commander": "1.2.0",
"api-blueprint-http-formatter": "0.0.1",
"http-string-parser": "0.0.4"
},
"devDependencies": {
"coffee-script": "1.6.3",
Expand All @@ -26,7 +28,10 @@
"http",
"message",
"request",
"repsponse"
"repsponse",
"api",
"blueprint",
"apiary"
],
"author": "Adam Kliment <adam@apiary.io>",
"license": "MIT",
Expand Down
28 changes: 28 additions & 0 deletions test/fixtures/get/expected-output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# GET /shopping-cart
+ Request
+ Headers

User-Agent:curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5
Host:curltraceparser.apiary.io
Accept:*/*

+ Body



+ Response 200
+ Headers

Content-Type:application/json
Date:Sun, 21 Jul 2013 13:23:55 GMT
X-Apiary-Ratelimit-Limit:120
X-Apiary-Ratelimit-Remaining:119
Content-Length:119
Connection:keep-alive

+ Body

{ "items": [
{ "url": "/shopping-cart/1", "product":"2ZY48XPZ", "quantity": 1, "name": "New socks", "price": 1.25 }
] }

28 changes: 28 additions & 0 deletions test/fixtures/post/expected-output.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# POST /shopping-cart
+ Request
+ Headers

User-Agent:curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8x zlib/1.2.5
Host:curltraceparser.apiary.io
Accept:*/*
Content-Type:application/json
Content-Length:39

+ Body

{ "product":"1AB23ORM", "quantity": 2 }

+ Response 201
+ Headers

Content-Type:application/json
Date:Sun, 21 Jul 2013 14:51:09 GMT
X-Apiary-Ratelimit-Limit:120
X-Apiary-Ratelimit-Remaining:119
Content-Length:50
Connection:keep-alive

+ Body

{ "status": "created", "url": "/shopping-cart/2" }

34 changes: 32 additions & 2 deletions test/integration/cli-test.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ describe "Command line", () ->
done error
done()

describe "parsing from standard input", () ->
describe "parsing from standard input with --raw", () ->
stdout = ""
stderr = ""
exitStatus = ""

before (done) ->
cmd = 'cat ./test/fixtures/get/tracefile | ' +
'./bin/curl-trace-parser'
'./bin/curl-trace-parser --raw'

cli = exec cmdPrefix + cmd, (error, out, err) ->
stdout = out
Expand All @@ -43,6 +43,36 @@ describe "Command line", () ->
assert.equal stdout, expected
done()

describe "parsing from standard input with --blueprint option", () ->
stdout = ""
stderr = ""
exitStatus = ""

before (done) ->
cmd = 'cat ./test/fixtures/post/tracefile | ' +
'./bin/curl-trace-parser --blueprint'

cli = exec cmdPrefix + cmd, (error, out, err) ->
stdout = out
stderr = err
if error
exitStatus = error.status
done()

cli.on 'exit', (code) ->
exitStatus = code

it "should not return nothing to stderr", () ->
assert.equal stderr, ""

it "should return with exit code 0", () ->

it "should return parsed body in API Blueprint format to standard output", (done) ->
expectedOutputPath = "./test/fixtures/post/expected-output.md"
fs.readFile expectedOutputPath, 'utf8', (err, expected) ->
assert.equal stdout, expected
done()

describe "no input on stdin and no options", ()->

stdout = ""
Expand Down