Skip to content

Commit d21b225

Browse files
committed
Preserve non-standard/unparseable query strings as-is in snippet output
This is particularly notable for cases like the &&& repro here, but is also clearly visible in cases like ?a=b&c, which would often become something more like '?a=b&c='. This only applies when the queryString in the HAR is empty, which will be rare, but HTTP Toolkit (and others) can use this to leave that blank and send only the raw URL to preserve formatting at the cost of the losing the nice structure query param setting code in the output.
1 parent bf61e2e commit d21b225

37 files changed

+348
-14
lines changed

src/index.js

+23-14
Original file line numberDiff line numberDiff line change
@@ -219,20 +219,29 @@ HTTPSnippet.prototype.prepare = function (request) {
219219
// merge all possible queryString values
220220
request.queryObj = Object.assign(request.queryObj, request.uriObj.query)
221221

222-
// reset uriObj values for a clean url
223-
request.uriObj.query = null
224-
request.uriObj.search = null
225-
request.uriObj.path = request.uriObj.pathname
226-
227-
// keep the base url clean of queryString
228-
request.url = url.format(request.uriObj)
229-
230-
// update the uri object
231-
request.uriObj.query = request.queryObj
232-
request.uriObj.search = qs.stringify(request.queryObj)
233-
234-
if (request.uriObj.search) {
235-
request.uriObj.path = request.uriObj.pathname + '?' + request.uriObj.search
222+
// In some cases (unparseable query - preference to use raw in exporter) the queryString might
223+
// be empty while the URL search is not. In that case, we prefer the URL search.
224+
const hasQueryObj = Object.keys(request.queryObj).length > 0
225+
if (hasQueryObj || !request.uriObj.search) {
226+
// reset uriObj values for a clean url
227+
request.uriObj.query = null
228+
request.uriObj.search = null
229+
request.uriObj.path = request.uriObj.pathname
230+
231+
// keep the base url clean of queryString
232+
request.url = url.format(request.uriObj)
233+
234+
// update the uri object
235+
request.uriObj.query = request.queryObj
236+
request.uriObj.search = qs.stringify(request.queryObj)
237+
238+
if (request.uriObj.search) {
239+
request.uriObj.path = request.uriObj.pathname + '?' + request.uriObj.search
240+
}
241+
} else {
242+
// We have no request.queryObj (so snippets won't send query params in a structured way)
243+
// We keep the queryString in request.url (so it's sent raw everywhere)
244+
// request.fullUrl is recreated below (maybe mild fixed?) but preserves raw search etc
236245
}
237246

238247
// construct a full url
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CURL *hnd = curl_easy_init();
2+
3+
curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
4+
curl_easy_setopt(hnd, CURLOPT_URL, "http://mockbin.com/har?&&&");
5+
6+
CURLcode ret = curl_easy_perform(hnd);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
(require '[clj-http.client :as client])
2+
3+
(client/get "http://mockbin.com/har?&&&")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
var client = new HttpClient();
2+
var request = new HttpRequestMessage
3+
{
4+
Method = HttpMethod.Get,
5+
RequestUri = new Uri("http://mockbin.com/har?&&&"),
6+
};
7+
using (var response = await client.SendAsync(request))
8+
{
9+
response.EnsureSuccessStatusCode();
10+
var body = await response.Content.ReadAsStringAsync();
11+
Console.WriteLine(body);
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
var client = new RestClient("http://mockbin.com/har?&&&");
2+
var request = new RestRequest(Method.GET);
3+
IRestResponse response = client.Execute(request);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"io"
7+
)
8+
9+
func main() {
10+
11+
url := "http://mockbin.com/har?&&&"
12+
13+
req, _ := http.NewRequest("GET", url, nil)
14+
15+
res, _ := http.DefaultClient.Do(req)
16+
17+
defer res.Body.Close()
18+
body, _ := io.ReadAll(res.Body)
19+
20+
fmt.Println(res)
21+
fmt.Println(string(body))
22+
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GET /har?&&& HTTP/1.1
2+
Host: mockbin.com
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
AsyncHttpClient client = new DefaultAsyncHttpClient();
2+
client.prepare("GET", "http://mockbin.com/har?&&&")
3+
.execute()
4+
.toCompletableFuture()
5+
.thenAccept(System.out::println)
6+
.join();
7+
8+
client.close();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
HttpRequest request = HttpRequest.newBuilder()
2+
.uri(URI.create("http://mockbin.com/har?&&&"))
3+
.method("GET", HttpRequest.BodyPublishers.noBody())
4+
.build();
5+
HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
6+
System.out.println(response.body());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
OkHttpClient client = new OkHttpClient();
2+
3+
Request request = new Request.Builder()
4+
.url("http://mockbin.com/har?&&&")
5+
.get()
6+
.build();
7+
8+
Response response = client.newCall(request).execute();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
HttpResponse<String> response = Unirest.get("http://mockbin.com/har?&&&")
2+
.asString();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import axios from "axios";
2+
3+
const options = {method: 'GET', url: 'http://mockbin.com/har?&&&'};
4+
5+
axios.request(options).then(function (response) {
6+
console.log(response.data);
7+
}).catch(function (error) {
8+
console.error(error);
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const options = {method: 'GET'};
2+
3+
fetch('http://mockbin.com/har?&&&', options)
4+
.then(response => response.json())
5+
.then(response => console.log(response))
6+
.catch(err => console.error(err));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
const settings = {
2+
"async": true,
3+
"crossDomain": true,
4+
"url": "http://mockbin.com/har?&&&",
5+
"method": "GET",
6+
"headers": {}
7+
};
8+
9+
$.ajax(settings).done(function (response) {
10+
console.log(response);
11+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
const data = null;
2+
3+
const xhr = new XMLHttpRequest();
4+
xhr.withCredentials = true;
5+
6+
xhr.addEventListener("readystatechange", function () {
7+
if (this.readyState === this.DONE) {
8+
console.log(this.responseText);
9+
}
10+
});
11+
12+
xhr.open("GET", "http://mockbin.com/har?&&&");
13+
14+
xhr.send(data);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
val client = OkHttpClient()
2+
3+
val request = Request.Builder()
4+
.url("http://mockbin.com/har?&&&")
5+
.get()
6+
.build()
7+
8+
val response = client.newCall(request).execute()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
var axios = require("axios").default;
2+
3+
var options = {method: 'GET', url: 'http://mockbin.com/har?&&&'};
4+
5+
axios.request(options).then(function (response) {
6+
console.log(response.data);
7+
}).catch(function (error) {
8+
console.error(error);
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const fetch = require('node-fetch');
2+
3+
let url = 'http://mockbin.com/har?&&&';
4+
5+
let options = {method: 'GET'};
6+
7+
fetch(url, options)
8+
.then(res => res.json())
9+
.then(json => console.log(json))
10+
.catch(err => console.error('error:' + err));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const http = require("http");
2+
3+
const options = {
4+
"method": "GET",
5+
"hostname": "mockbin.com",
6+
"port": null,
7+
"path": "/har?&&&",
8+
"headers": {}
9+
};
10+
11+
const req = http.request(options, function (res) {
12+
const chunks = [];
13+
14+
res.on("data", function (chunk) {
15+
chunks.push(chunk);
16+
});
17+
18+
res.on("end", function () {
19+
const body = Buffer.concat(chunks);
20+
console.log(body.toString());
21+
});
22+
});
23+
24+
req.end();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const request = require('request');
2+
3+
const options = {method: 'GET', url: 'http://mockbin.com/har?&&&'};
4+
5+
request(options, function (error, response, body) {
6+
if (error) throw new Error(error);
7+
8+
console.log(body);
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
const unirest = require("unirest");
2+
3+
const req = unirest("GET", "http://mockbin.com/har?&&&");
4+
5+
req.end(function (res) {
6+
if (res.error) throw new Error(res.error);
7+
8+
console.log(res.body);
9+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#import <Foundation/Foundation.h>
2+
3+
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://mockbin.com/har?&&&"]
4+
cachePolicy:NSURLRequestUseProtocolCachePolicy
5+
timeoutInterval:10.0];
6+
[request setHTTPMethod:@"GET"];
7+
8+
NSURLSession *session = [NSURLSession sharedSession];
9+
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
10+
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
11+
if (error) {
12+
NSLog(@"%@", error);
13+
} else {
14+
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
15+
NSLog(@"%@", httpResponse);
16+
}
17+
}];
18+
[dataTask resume];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
open Cohttp_lwt_unix
2+
open Cohttp
3+
open Lwt
4+
5+
let uri = Uri.of_string "http://mockbin.com/har?&&&" in
6+
7+
Client.call `GET uri
8+
>>= fun (res, body_stream) ->
9+
(* Do stuff with the result *)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
$curl = curl_init();
4+
5+
curl_setopt_array($curl, [
6+
CURLOPT_URL => 'http://mockbin.com/har?&&&',
7+
CURLOPT_RETURNTRANSFER => true,
8+
CURLOPT_ENCODING => '',
9+
CURLOPT_MAXREDIRS => 10,
10+
CURLOPT_TIMEOUT => 30,
11+
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
12+
CURLOPT_CUSTOMREQUEST => 'GET',
13+
]);
14+
15+
$response = curl_exec($curl);
16+
$err = curl_error($curl);
17+
18+
curl_close($curl);
19+
20+
if ($err) {
21+
echo 'cURL Error #:' . $err;
22+
} else {
23+
echo $response;
24+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
$request = new HttpRequest();
4+
$request->setUrl('http://mockbin.com/har?&&&');
5+
$request->setMethod(HTTP_METH_GET);
6+
7+
try {
8+
$response = $request->send();
9+
10+
echo $response->getBody();
11+
} catch (HttpException $ex) {
12+
echo $ex;
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
$client = new http\Client;
4+
$request = new http\Client\Request;
5+
6+
$request->setRequestUrl('http://mockbin.com/har?&&&');
7+
$request->setRequestMethod('GET');
8+
$client->enqueue($request)->send();
9+
$response = $client->getResponse();
10+
11+
echo $response->getBody();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$response = Invoke-RestMethod -Uri 'http://mockbin.com/har?&&&' -Method GET
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
$response = Invoke-WebRequest -Uri 'http://mockbin.com/har?&&&' -Method GET
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import http.client
2+
3+
conn = http.client.HTTPConnection("mockbin.com")
4+
5+
conn.request("GET", "/har?&&&")
6+
7+
res = conn.getresponse()
8+
data = res.read()
9+
10+
print(data.decode("utf-8"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import requests
2+
3+
url = "http://mockbin.com/har?&&&"
4+
5+
response = requests.get(url)
6+
7+
print(response.text)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
library(httr)
2+
3+
url <- "http://mockbin.com/har?&&&"
4+
5+
response <- VERB("GET", url, content_type("application/octet-stream"))
6+
7+
content(response, "text")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
require 'uri'
2+
require 'net/http'
3+
4+
url = URI("http://mockbin.com/har?&&&")
5+
6+
http = Net::HTTP.new(url.host, url.port)
7+
8+
request = Net::HTTP::Get.new(url)
9+
10+
response = http.request(request)
11+
puts response.read_body

0 commit comments

Comments
 (0)