forked from pbnjay/harhar
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor code to use http.RoundTripper
- Loading branch information
Showing
4 changed files
with
98 additions
and
206 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,64 +1,20 @@ | ||
harhar | ||
====== | ||
|
||
Simple, transparent HTTP Archive (HAR) logging for Go code using the | ||
http.Client interface. For existing code that already uses the `net/http` | ||
package, updating existing code to generate HAR logs can typically be done | ||
with only 2 lines of code. | ||
HTTP Archive (HAR) recording for Go code using the http.RoundTripper interface. | ||
|
||
Getting Started | ||
--------------- | ||
|
||
First, convert your existing http.Client instance (or http.DefaultClient) to | ||
a harhar.Client: | ||
For logging from an `http.Client` you can simply set the Transport property: | ||
|
||
// before | ||
webClient := &http.Client{} | ||
|
||
// after | ||
httpClient := &http.Client{} | ||
webClient := harhar.NewClient(httpClient) | ||
|
||
Then, whenever you're ready to generate the HAR output, call WriteLog: | ||
|
||
webClient.WriteLog("output.har") | ||
|
||
That's it! harhar.Client implements all the same methods as http.Client, so no | ||
other code will need to be changed. However, if you set Timeouts, Cookies, etc. | ||
dynamically then you will want to retain a copy of the wrapped http.Client. | ||
harhar.Client only stores the pointer, so changes to the underlying http.Client | ||
will be used immediately. | ||
|
||
Optional periodic logging | ||
------------------------- | ||
|
||
To dynamically enable or disable HAR logging, code can use harhar.ClientInterface | ||
to represent either an http.Client or harhar.Client. The included `harhar` example | ||
command shows one way to use this interface. When using this interface, you can | ||
write logs (if enabled) by using this simple block of code: | ||
|
||
if harCli, ok := myClient.(*harhar.Client); ok { | ||
harCli.WriteLog("output.har") | ||
```go | ||
recorder := harhar.NewRecorder(http.DefaultTransport) | ||
client := &http.Client{ | ||
Transport: recorder, | ||
} | ||
``` | ||
|
||
When combined with a long-running process, the interface makes it possible to | ||
toggle logging off and on, and periodically write to disk throughout a processes | ||
lifetime. An example is the following (never-ending) goroutine: | ||
|
||
go func(){ | ||
for _ = range time.Tick(time.Minute*5) { | ||
if harCli, ok := myClient.(*harhar.Client); ok { | ||
sz, err := harCli.WriteLog("output.har") | ||
if err!=nil { | ||
log.Println("error writing .har log:", err) | ||
} else { | ||
log.Printf("wrote .har log (%.1fkb)\n", float64(sz)/1024.0) | ||
} | ||
} | ||
} | ||
}() | ||
Then, whenever you're ready to generate the HAR output, call WriteFile: | ||
|
||
Note that when logging is enabled, harhar memory usage can grow pretty quickly, | ||
especially if Responses are large. If you don't want to disable logging in code | ||
when output size grows too large, you should at least display it so that users | ||
can decide to stop before the OOM killer comes to play. | ||
recorder.WriteFile("output.har") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,75 +1,46 @@ | ||
// This command will do a GET request on a provided list of URLs, optionally | ||
// logging them to the HAR file. It's a simple example that concisely showcases | ||
// all the features and usage. | ||
// This command will do a GET request on a provided URL and log the result to a HAR file. | ||
// It's a simple example that concisely showcases all the features and usage. | ||
|
||
package main | ||
|
||
import ( | ||
"flag" | ||
"io/ioutil" | ||
"log" | ||
"net/http" | ||
"os" | ||
"strings" | ||
|
||
"github.com/stridatum/harhar" | ||
) | ||
|
||
var ( | ||
input = flag.String("urls", "", "input urls (one per line)") | ||
output = flag.String("har", "", "output har to file") | ||
|
||
// client uses the interface just to show how it works. | ||
// typically you'd use this so that you can toggle logging on an off | ||
// at will to conserve memory usage. | ||
client harhar.ClientInterface = &http.Client{} | ||
harhar ".." | ||
) | ||
|
||
func main() { | ||
var ( | ||
u = flag.String("url", "", "url to read") | ||
output = flag.String("har", "", "output har to file") | ||
) | ||
|
||
flag.Parse() | ||
if *input == "" { | ||
|
||
if *u == "" || *output == "" { | ||
flag.Usage() | ||
os.Exit(1) | ||
} | ||
|
||
if *output == "" { | ||
log.Println("-har not provided, no .har file will be produced") | ||
} else { | ||
// wrap the http.Client to transparently track requests | ||
client = harhar.NewClient(client.(*http.Client)) | ||
} | ||
recorder := harhar.NewRecorder() | ||
client := &http.Client{Transport: recorder} | ||
|
||
//////// | ||
|
||
// read in a file consisting of 1 line per URL, and do a GET on each. | ||
data, err := ioutil.ReadFile(*input) | ||
resp, err := client.Get(*u) | ||
if err != nil { | ||
log.Println("error reading input: ", err) | ||
os.Exit(1) | ||
} | ||
for _, line := range strings.Split(string(data), "\n") { | ||
line = strings.TrimSpace(line) | ||
if line == "" { | ||
continue | ||
} | ||
resp, err := client.Get(line) | ||
if err != nil { | ||
log.Println("error in GET to", line) | ||
} else { | ||
log.Printf("Got %s from %s\n", resp.Status, line) | ||
} | ||
log.Fatal(err) | ||
} | ||
|
||
/////////// | ||
log.Printf("got %s from %s\n", resp.Status, *u) | ||
|
||
if *output != "" { | ||
size, err := client.(*harhar.Client).WriteLog(*output) | ||
if err == nil { | ||
// it's always good to report size when logging since memory usage | ||
// will grow pretty quickly if you're not careful. | ||
log.Printf("wrote %s (%.1fkb)\n", *output, float64(size)/1024.0) | ||
} else { | ||
log.Println("error writing har: ", err) | ||
} | ||
size, err := recorder.WriteFile(*output) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// it's always good to report size when logging since memory usage | ||
// will grow pretty quickly if you're not careful. | ||
log.Printf("wrote %s (%.1fkb)\n", *output, float64(size)/1024.0) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.