0

I am trying to make a function where it hosts your file on the anonfiles.com website using the anonfiles API. Even thought I am correctly using the api, it always returns nil. Response is missing message.

screenshot

func host(file string) {
    fileBytes, err := ioutil.ReadFile(file)
    if err != nil {
        fmt.Println("\033[1;31mCommand > Host: Could not read file,", err, "\033[0m")
        return
    }

    url := "https://api.anonfiles.com/upload"

    request, err := http.NewRequest("POST", url, bytes.NewBuffer(fileBytes))
    if err != nil {
        fmt.Println("\033[1;31mCommand > Host: Could not post request,", err, "\033[0m")
        return
    }

    request.Header.Set("Content-Type", "application/octet-stream")

    client := &http.Client{}
    response, err := client.Do(request)
    if err != nil {
        fmt.Println("\033[1;31mCommand > Host: Could not send request,", err, "\033[0m")
        return
    }
    defer response.Body.Close()

    body, err := ioutil.ReadAll(response.Body)
    if err != nil {
        fmt.Println("\033[1;31mCommand > Host: Could not read response,", err, "\033[0m")
        return
    }

    var result map[string]interface{}
    err = json.Unmarshal(body, &result)
    if err != nil {
        fmt.Println("\033[1;31mCommand > Host: Could not parse response,", err, "\033[0m")
        return
    }

    if response.StatusCode == 200 {
        if result["url"] == nil {
            fmt.Println("\033[1;31mCommand > Host: Response is missing URL\033[0m")
            return
        }
        fmt.Println("File hosted successfully:", result["url"].(string))
    } else {
        if result["message"] == nil {
            fmt.Println("\033[1;31mCommand > Host: Response is missing message\033[0m")
            return
        }
        fmt.Println("\033[1;31mCommand > Host:\033[0m", result["message"].(string))
    }
}
iVers
  • 25
  • 4
  • According to [the documentation](https://anonfiles.com/docs/api), you need to be sending the file content encoded as `multipart/form-data`, with the content in the `file` parameter. Take a look at the `curl` example -- try with `curl --trace-ascii request.log`, and then inspect `request.log` to see exactly what is being sent. – larsks Feb 05 '23 at 16:41
  • [This question](https://stackoverflow.com/questions/20205796/post-data-using-the-content-type-multipart-form-data) may be useful. – larsks Feb 05 '23 at 16:43
  • @larsks yes, i tried curl as well, it didnt work. I believe the method is not the issue here, as its doing the same thing as curl. Also, you can see from my error handler message the the request is being sent and marked as valid but it gives no response, so thats where the issue actually is. – iVers Feb 05 '23 at 19:25
  • The `curl` example they post on their web site works as written. If I send data the same way -- as a multipart/form-data upload -- it works just fine. – larsks Feb 05 '23 at 21:55

1 Answers1

0

I'd thought I'd take a moment to expand those comments into an answer.

First, as we we've already discussed, you're not using the correct API to upload files. If we modify your code to show the complete response body, like this:

client := &http.Client{}
response, err := client.Do(request)
if err != nil {
  fmt.Println("\033[1;31mCommand > Host: Could not send request,", err, "\033[0m")
  return
}
defer response.Body.Close()

body, err := ioutil.ReadAll(response.Body)
if err != nil {
  fmt.Println("\033[1;31mCommand > Host: Could not read response,", err, "\033[0m")
  return
}

fmt.Printf("BODY:\n%s\n", body)

We see the following:

{
  "status": false,
  "error": {
    "message": "No file chosen.",
    "type": "ERROR_FILE_NOT_PROVIDED",
    "code": 10
  }
}

We're getting this error because you're not providing the file parameter in a multipart/form-data request. The post to which I linked earlier has several examples of sending a multipart request; I've tested a couple of them and they seem to work as expected.


You're also making incorrect assumptions about the response returned by the API. If we make a successful request using curl and capture the response JSON, we find that it looks like this:

{
  "status": true,
  "data": {
    "file": {
      "url": {
        "full": "https://anonfiles.com/k8cdobWey7/test_txt",
        "short": "https://anonfiles.com/k8cdobWey7"
      },
      "metadata": {
        "id": "k8cdobWey7",
        "name": "test.txt",
        "size": {
          "bytes": 12,
          "readable": "12 B"
        }
      }
    }
  }
}

Note that there is no response["url"] or response["message"]. If you want the URL for the uploaded file, you need to get response["data"]["file"]["url"]["full"] (or ["short"]).

Similarly, we can see examples of the error response above, which looks like this:

{
  "status": false,
  "error": {
    "message": "No file chosen.",
    "type": "ERROR_FILE_NOT_PROVIDED",
    "code": 10
  }
}

That's not result["message"]; that's result["error"]["message"].

Because you're unmarshalling into a map[string]interface, getting at these nested keys is going to be a bit of a pain. I found it easiest to create Go structs for the above responses, and just unmarshal into an appropriately typed variable.

That gets me the following types:

type (
  AnonFilesUrl struct {
    Full  string `json:"full"`
    Short string `json:"short"`
  }

  AnonFilesMetadata struct {
    ID   string `json:"id"`
    Name string `json:"name"`
    Size struct {
      Bytes    int    `json:"bytes"`
      Readable string `json:"readable"`
    } `json:"size"`
  }

  AnonFilesData struct {
    File struct {
      URL      AnonFilesUrl      `json:"url"`
      Metadata AnonFilesMetadata `json:"metadata"`
    } `json:"file"`
  }

  AnonFilesError struct {
    Message string
    Type    string
    Code    int
  }

  AnonFilesResponse struct {
    Status bool           `json:"status"`
    Data   AnonFilesData  `json:"data"`
    Error  AnonFilesError `json:"error"`
  }
)

And then unmarshalling the response looks like:

var result AnonFilesResponse
err = json.Unmarshal(body, &result)

And we can ask for fields like:

fmt.Printf("URL: %s\n", result.Data.File.URL.Full)
larsks
  • 277,717
  • 41
  • 399
  • 399