Last active
August 15, 2016 13:09
-
-
Save erithmetic/e9183ae0f2539c3e6961c824b1865e15 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
package main | |
import ( | |
"bufio" | |
"encoding/json" | |
"log" | |
"os" | |
) | |
type requestDetails struct { | |
Path string `json:"path"` | |
Method string `json:"method"` | |
Destination string `json:"destination"` // hostname | |
Scheme string `json:"scheme"` | |
Query string `json:"query"` | |
Body string `json:"body"` | |
Headers map[string][]string `json:"headers"` | |
} | |
// Payload structure holds request and response structure | |
type Payload struct { | |
Request requestDetails `json:"request"` | |
ID string `json:"id"` | |
} | |
func main() { | |
// logging to stderr | |
l := log.New(os.Stderr, "", 0) | |
s := bufio.NewScanner(os.Stdin) | |
for s.Scan() { | |
var payload Payload | |
err := json.Unmarshal(s.Bytes(), &payload) | |
if err != nil { | |
l.Println("Failed to unmarshal payload from hoverfly") | |
} | |
if payload.Request.Destination == "api.io" { | |
payload.Request.Scheme = "https"; | |
} | |
bts, err := json.Marshal(payload) | |
if err != nil { | |
l.Println("Failed to marshal new payload") | |
} | |
os.Stdout.Write(bts) | |
} | |
} |
This file contains hidden or 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
{ | |
"data":[ | |
{ | |
"response":{ | |
"status":400, | |
"body":"{\"code\": 400, \"status\": {\"code\": -1204, \"message\": \"Bad request\"}}\n", | |
"encodedBody":false, | |
"headers":{ | |
"Cache-Control":[ | |
"max-age=0, no-cache, no-store, must-revalidate" | |
], | |
"Content-Length":[ | |
"67" | |
], | |
"Content-Type":[ | |
"application/json" | |
], | |
"Date":[ | |
"Fri, 12 Aug 2016 18:23:49 GMT" | |
], | |
"Etag":[ | |
"\"55930e11-43\"" | |
], | |
"Hoverfly":[ | |
"Was-Here" | |
], | |
"Server":[ | |
"nginx" | |
], | |
"X-Content-Type-Options":[ | |
"nosniff" | |
], | |
"X-Frame-Options":[ | |
"SAMEORIGIN" | |
], | |
"X-Ua-Compatible":[ | |
"IE=Edge" | |
], | |
"X-Xss-Protection":[ | |
"1; mode=block" | |
] | |
} | |
}, | |
"request":{ | |
"path":"/andromeda/source", | |
"method":"POST", | |
"destination":"api.io", | |
"scheme":"https", | |
"query":"username=foo;api_key=bar", | |
"body":"----------------------------520377437903499113890966\r\nContent-Disposition: form-data; name=\"file\"; filename=\"116-7-12-6-23-12wm010.csv\"\r\nContent-Type: text/csv\r\n\r\nstuff,to,export\r\r1,2,3----------------------------520377437903499113890966\r\nContent-Disposition: form-data; name=\"name\"\r\n\r\nMy Company\r\n----------------------------520377437903499113890966--", | |
"headers":{ | |
"Connection":[ | |
"close" | |
], | |
"Content-Type":[ | |
"multipart/form-data; boundary=--------------------------520377437903499113890966" | |
] | |
} | |
} | |
} |
This file contains hidden or 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
def use_simulation(name, &blk) | |
file = File.join(SIMULATION_PATH, "#{name}.json") | |
if record_mode = File.exist?(file) | |
puts "Using simulation #{file}" | |
upload_simulation file | |
start_simulation | |
else | |
puts "No recorded simulation at #{file}, recording from scratch" | |
start_recording | |
configure_middleware | |
end | |
blk.call | |
puts "Saving recorded simulation #{file}" | |
save_simulation file | |
end | |
def upload_simulation(file) | |
RestClient::Request.execute( | |
method: :get, | |
url: URI.join(HOVERFLY_API_URL, "/api/records").to_s, | |
payload: File.read(file) | |
) | |
end | |
def start_simulation | |
RestClient::Request.execute( | |
method: :post, | |
url: URI.join(HOVERFLY_API_URL, "/api/state").to_s, | |
headers: { 'Content-Type' => 'application/json' }, | |
payload: '{"mode":"simulate"}' | |
) | |
end | |
def start_recording | |
RestClient::Request.execute( | |
method: :post, | |
url: URI.join(HOVERFLY_API_URL, "/api/state").to_s, | |
headers: { 'Content-Type' => 'application/json' }, | |
payload: '{"mode":"capture"}' | |
) | |
end | |
def configure_middleware | |
RestClient::Request.execute( | |
method: :post, | |
url: URI.join(HOVERFLY_API_URL, "/api/middleware").to_s, | |
headers: { 'Content-Type' => 'application/json' }, | |
payload: '{"middleware":"/faraday-middleware/rewrite_scheme"}' | |
) | |
end | |
def save_simulation(file) | |
response = RestClient::Request.execute( | |
method: :get, | |
url: URI.join(HOVERFLY_API_URL, "/api/records").to_s | |
) | |
File.open file, 'w' do |f| | |
f.puts response.body | |
end | |
end |
Also note that I am seeing the requests in the hoverfly logs:
fake_1 | [negroni] Started POST /api/state
fake_1 | {"body":"{\"mode\":\"capture\"}","destination":"","level":"info","msg":"Handling state change request!","newState":"capture","time":"2016-08-12T18:23:35Z"}
fake_1 | [negroni] Completed 200 OK in 149.533µs
fake_1 | [negroni] Started POST /api/middleware
fake_1 | [negroni] Completed 200 OK in 1.326917ms
fake_1 | {"destination":"api.io","level":"info","method":"POST","middleware":"/faraday-middleware/rewrite_scheme","mode":"capture","msg":"request and response captured","path":"/andromeda/source","rawQuery":"username=foo;api_key=bar","time":"2016-08-12T18:23:48Z"}
fake_1 | {"destination":"api.io","level":"info","method":"POST","middleware":"/faraday-middleware/rewrite_scheme","mode":"capture","msg":"request and response captured","path":"/andromeda/source","rawQuery":"username=foo;api_key=bar","time":"2016-08-12T18:23:48Z"}
fake_1 | {"destination":"api.io","level":"info","method":"POST","middleware":"/faraday-middleware/rewrite_scheme","mode":"capture","msg":"request and response captured","path":"/andromeda/source","rawQuery":"username=foo;api_key=bar","time":"2016-08-12T18:23:49Z"}
fake_1 | {"destination":"api.io","level":"info","method":"POST","middleware":"/faraday-middleware/rewrite_scheme","mode":"capture","msg":"request and response captured","path":"/andromeda/source","rawQuery":"username=foo;api_key=bar","time":"2016-08-12T18:23:49Z"}
fake_1 | [negroni] Started GET /api/records
fake_1 | [negroni] Completed 200 OK in 641.116µs
Hey @dkastner,
I was able to reproduce the error using Nodejs with Hoverfly.
Error: self signed certificate in certificate chain
at Error (native)
at TLSSocket.<anonymous> (_tls_wrap.js:1060:38)
at emitNone (events.js:86:13)
at TLSSocket.emit (events.js:185:7)
at TLSSocket._finishInit (_tls_wrap.js:584:8)
at TLSWrap.ssl.onhandshakedone (_tls_wrap.js:416:38)
Having spent some time thinking about it, I don't think producing middleware to terminate the SSL at Hoverfly is the best thing to do.
The best working solution we have so far is by changing the NODE_TLS_REJECT_UNAUTHORIZED to false so that Nodejs ignores the self-signed certificate.
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
We acknowledge that this isn't ideal but likewise, we can't really give out a signed public and private set of keys. It might be possible to generate a set of keys using Let's Encrypt and then giving them both to Hoverfly, though this isn't something we've done yet.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I've also updated my middleware to strip out the Content-Length header to no avail