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

Lines changed: 23 additions & 14 deletions
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
Lines changed: 6 additions & 0 deletions
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);
Lines changed: 3 additions & 0 deletions
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?&&&")
Lines changed: 12 additions & 0 deletions
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+
}
Lines changed: 3 additions & 0 deletions
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);
Lines changed: 23 additions & 0 deletions
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+
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GET /har?&&& HTTP/1.1
2+
Host: mockbin.com
Lines changed: 8 additions & 0 deletions
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();
Lines changed: 6 additions & 0 deletions
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());
Lines changed: 8 additions & 0 deletions
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();

0 commit comments

Comments
 (0)