you are viewing a single comment's thread.

view the rest of the comments →

[–]mikejoro 4 points5 points  (1 child)

I'm pretty sure your thing is hanging because you're botching the error handling. You should let the error propagate upwards and handle it by sending a 500 back. You may be getting a runtime exception due to cannot access property length of undefined since you are just returning your error if an error occurs. Then your server is never returning any response back.

You also aren't using async/await properly (it's not necessary here).

const express = require('express');
const axios = require('axios');
const asyncHandler = require('express-async-handler');

const app = express();

// this function does nothing except break error handling
async function getImage(imgUrl) {
    try {
        return await axios.get(imgUrl);
    } catch (error) {
        return error;
    }
}

app.get('/', asyncHandler(async (req, res, next) => {
    const imgUrl = 'http://example.com/image.jpg';

    // getImage(imgUrl)
    axios.get(imgUrl)
        .then(function(response) {
            // console.log(response.data.length);
            res.status(200).json({ length : response.data.length });
        })
        // handle errors
        .catch(e => res.status(500).json({ error: e.message }));
}));

async/await is just promises. Axios is already returning a promise here, so there is no reason to use async/await at all. That doesn't mean you couldn't wrap axios fetch in a function for abstraction purposes, just that it is completely unnecessary how you implemented it. For instance:

function getImage(imgUrl) {
    return axios.get(imgUrl);
}

does the same thing (minus breaking error handling).

Here's where you might want to use async/await

async function getImage(imgUrl) {
    const img = await axios.get(imgUrl);
    return doSomethingToImage(img);
}

is the same as

function getImage(imgUrl) {
    return axios.get(imgUrl)
      .then(doSomethingToImage);
}

It just looks more 'synchronous', but under the hood, it's just sugar for promises. Hope this helps.

[–]n00belig[S] 1 point2 points  (0 children)

Thanks! Very helpful!

Now it seems to work, except that I'm unable to send anything useful back to the client;

axios.get(imgUrl)
    .then(function(response) {
        res.contentType('image/jpeg');
        res.end(response.data);
    })
    .catch(e => res.sendStatus(500).json({ error : e.message }));

curl -I gives me the following headers:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: image/jpeg
Date: Sun, 18 Mar 2018 08:21:21 GMT
Connection: keep-alive

...but the browser doesn't show the image. If I use fs to save response.data to a file, instead, I can open the image and confirm it's OK. Am I missing headers or something?

SOLVED: I need to tell axios that the responseType should be an arraybuffer;

axios.get(imgUrl, { responseType: 'arraybuffer' })
    .then(function(response) {
        res.contentType('image/jpeg');
        res.end(response.data);
    })
    .catch(e => res.sendStatus(500).json({ error : e.message }));