Search code examples
gohttpartifactoryartifactory-query-lang

Is there a way to clean this POST request of backslashes before I send it off?


I'm writing a program that sends a POST request whose body requires double quotes in plaintext. Because I'm injecting variables with fmt.Sprintf everytime I send a request, I'm using string literals when sending the request off

func searchLocalImage(imageName, imageTag, artifactoryUsername, artifactoryPassword string) (localImageRepo string) {
    a := types.ArtifactoryClient{
        Url:      "<url>",
        Username: artifactoryUsername,
        Password: artifactoryPassword,
        Client:   resty.New(),
    }
    var responseBody map[string]interface{}

    url := a.Url + "/search/aql"
    res, _ := a.Client.R().
        SetHeader("Content-Type", "text/plain").
        SetBasicAuth(a.Username, a.Password).
        SetBody(fmt.Sprintf(`items.find({"$and": [{"repo":{"$match":"<folder>"}},{"path": {"$match":"%s/%s"}},{"name":{"$match":"<tag>"}}]}).include("repo","path","name")`, imageName, imageTag)).
        Post(url)

Of course, this automatically injects escape characters to returned string.

"items.find({\"$and\": [{\"repo\":{\"$match\":\"<folder>\"}},{\"path\": {\"$match\":\"<folderPath>\"}},{\"name\":{\"$match\":\"<tag>\"}}]}).include(\"repo\",\"path\",\"name\")"

This unfortunately results in the response being an error message. Has anybody found a way to send a request like this the way I would need to without also sending those backslashes?


Solution

  • Of course, this automatically injects escape characters to returned string.

    No, this is not true. You see the escape characters because the tool that you used (most likely a debugger) displays the content as a quoted string.

    You can simply dump the request to see what is sent. And paste the dump content into Insomnia to find out what's wrong.

    package main
    
    import (
        "fmt"
        "net/http"
        "net/http/httptest"
        "net/http/httputil"
    
        "github.com/go-resty/resty/v2"
    )
    
    func main() {
        ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            buf, err := httputil.DumpRequest(r, true)
            if err != nil {
                panic(err)
            }
    
            fmt.Printf("%s\n", buf)
        }))
        defer ts.Close()
    
        client := resty.New()
    
        imageName := "image name"
        imageTag := "image tag"
        _, err := client.R().
            SetHeader("Content-Type", "text/plain").
            SetBasicAuth("<username>", "<password>").
            SetBody(fmt.Sprintf(`items.find({"$and": [{"repo":{"$match":"<folder>"}},{"path": {"$match":"%s/%s"}},{"name":{"$match":"<tag>"}}]}).include("repo","path","name")`, imageName, imageTag)).
            Post(ts.URL)
        if err != nil {
            panic(err)
        }
    }
    
    POST / HTTP/1.1
    Host: 127.0.0.1:41937
    Accept-Encoding: gzip
    Authorization: Basic PHVzZXJuYW1lPjo8cGFzc3dvcmQ+
    Content-Length: 156
    Content-Type: text/plain
    User-Agent: go-resty/2.7.0 (https://github.com/go-resty/resty)
    
    items.find({"$and": [{"repo":{"$match":"<folder>"}},{"path": {"$match":"image name/image tag"}},{"name":{"$match":"<tag>"}}]}).include("repo","path","name")