Home > Blockchain >  Send a File from url to cloudflare images fails
Send a File from url to cloudflare images fails

Time:04-05

I'm using Google App engine so that means writing files is only allowed through cloud storage. When the API is hit, I can grab the file and store it in google cloud storage without issues. That function just returns the URL where it is saved. I want to get that image URL and then send it to Cloudflare images because they let you create variants.

type ImageResult struct {
            Result struct {
                ID                string    `json:"id"`
                Filename          string    `json:"filename"`
                Uploaded          time.Time `json:"uploaded"`
                RequireSignedURLs bool      `json:"requireSignedURLs"`
                Variants          []string  `json:"variants"`
            } `json:"result"`
            ResultInfo interface{}   `json:"result_info"`
            Success    bool          `json:"success"`
            Errors     []interface{} `json:"errors"`
            Messages   []interface{} `json:"messages"`
}

The above is the struct that represents the Cloudflare response. Below is the function to take the google cloud storage URL directly and "download" it before sending it off to Cloudflare.

func CloudFlareURL(url, filename string) (*ImageResult, error) {
    cloudFlareUrl := "https://api.cloudflare.com/client/v4/accounts/"   konsts.CloudFlareAcc   "/images/v1"
    cloudFlareAuth := "Bearer "   konsts.CloudFlareApi
    r, err := http.Get(url)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't get the file")
    }
    if r.StatusCode != 200 {
        return nil, errors.New("Couldn't get the file")
    }
    defer r.Body.Close()
    buff := make([]byte, 4096)
    _, err = r.Body.Read(buff)

    req, err := http.NewRequest("POST", cloudFlareUrl, bytes.NewReader(buff))
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't create the request")
    }
    req.Header.Set("Content-Type", "multipart/form-data")
    req.Header.Set("Authorization", cloudFlareAuth)

    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't send the request")
    }

    var result ImageResult
    bodi := &bytes.Buffer{}
    _, err = bodi.ReadFrom(resp.Body)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't read the response body")
    }
    resp.Body.Close()
    err = json.Unmarshal(bodi.Bytes(), &result)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't unmarshal the response body")
    }
    return &result, nil
}

This is the error message; invalid character 'E' looking for beginning of value Couldn't unmarshal the response body

Now on my laptop if I'm running the api server once a file has been sent I can save it on disk, open it and send to cloudflare with no problems. Here's the code for that

func CloudFlareFile(params map[string]string, paramName, path string) (*ImageResult, error) {
    file, err := os.Open(path)
    if err != nil {
        return nil, err
    }
    defer file.Close()

    body := &bytes.Buffer{}
    writer := multipart.NewWriter(body)
    part, err := writer.CreateFormFile(paramName, filepath.Base(path))
    if err != nil {
        return nil, err
    }
    _, err = io.Copy(part, file)

    for key, val := range params {
        _ = writer.WriteField(key, val)
    }
    err = writer.Close()
    if err != nil {
        return nil, err
    }
    cloudFlareUrl := "https://api.cloudflare.com/client/v4/accounts/"   konsts.CloudFlareAcc   "/images/v1"
    cloudFlareAuth := "Bearer "   konsts.CloudFlareApi
    req, err := http.NewRequest("POST", cloudFlareUrl, body)
    req.Header.Set("Content-Type", writer.FormDataContentType())
    req.Header.Set("Authorization", cloudFlareAuth)
    var result ImageResult
    client := &http.Client{}
    resp, err := client.Do(req)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't send the request")
    } else {
        body := &bytes.Buffer{}
        _, err := body.ReadFrom(resp.Body)
        if err != nil {
            return nil, errors.Wrap(err, "Couldn't read the response body")
        }
        resp.Body.Close()
        err = json.Unmarshal(body.Bytes(), &result)
        if err != nil {
            return nil, errors.Wrap(err, "Couldn't unmarshal the response body")
        }
    }
    return &result, nil
}
 

I've tried variations and it always fails. For example;

req, err := http.NewRequest("POST", cloudFlareUrl, r.body)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't create the request")
    }
    req.Header.Set("Content-Type", "multipart/form-data")
    req.Header.Set("Authorization", cloudFlareAuth)

CodePudding user response:

Ok for anyone else having this issue. I solved it.

r, err := http.Get(url)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't get the file")
    }
    if r.StatusCode != 200 {
        return nil, errors.New("Couldn't get the file")
    }
    defer r.Body.Close()
    b := &bytes.Buffer{}
    a := make([]byte, 4096)
    wr := multipart.NewWriter(b)
    part, err := wr.CreateFormFile("file", filename)
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't create the form file")
    }
    _, err = io.CopyBuffer(part, r.Body, a)
    wr.Close()

    req, err := http.NewRequest("POST", cloudFlareUrl, bytes.NewReader(b.Bytes()))
    if err != nil {
        return nil, errors.Wrap(err, "Couldn't create the request")
    }
    // req.Header.Set("Content-Type", "multipart/form-data")
    req.Header.Set("Content-Type", wr.FormDataContentType())
    req.Header.Set("Authorization", cloudFlareAuth)
  • Related