Skip to content

Commit

Permalink
feat(API): add API endpoint for GET
Browse files Browse the repository at this point in the history
Added a new API endpoint to generate thumbnails using GET method
  • Loading branch information
Antonio Pintus committed Jun 30, 2017
1 parent 48c7305 commit 1bf3612
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ RUN apt-get update && apt-get install -y curl wget python make g++ && apt-get -y
# nvm environment variables
ENV NVM_DIR /usr/local/nvm
# change Node.js versione here, if required
ENV NODE_VERSION 8.1.2
ENV NODE_VERSION 8.1.3

# install nvm
# https://github.com/creationix/nvm#install-script
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,29 @@ Example:
}
```


**GET /screenshots/{url}[?thumbnail=width,height]**

Gets a screenshot thumbnail for the specified `url` path parameter.
It returns a response with a base64 encoded stream body with `Content-Type` equal to `image/png`. The thumbnail will have the size
specified by the `thumbnail` query param.

Path parameter is:

- `url` - (required) string, complete **URL percent-encoding** URL of the page to capture;

Query parameter is:

- `thumbnail` - (optional) string in the form of `width,heigth` to generate a thumbnail of the specifies size. If not provided default is `160,100`.

Example:

```sh
curl --request GET \
--url 'http://<your-server>/screenshots/http%3A%2F%2Fwww.corriere.it?thumbnail=160%2C100' \
--header 'content-type: application/json'
```

---

# Docker
Expand Down
43 changes: 40 additions & 3 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const hfcOptions = {

const chrome = new HandsfreeChrome(hfcOptions);

// POST handler
const captureScreenshotHandler = async function (request, reply) {
try {
debug('capture invoked');
Expand All @@ -29,7 +30,7 @@ const captureScreenshotHandler = async function (request, reply) {
reply(error);
}
};

// POST config
const captureConfig = {
handler: captureScreenshotHandler,
validate: {
Expand All @@ -45,18 +46,54 @@ const captureConfig = {
}
}
}
// Add the route for the captureScreenshot API endpoint

// GET handler
const captureThumbnailHandler = async function (request, reply) {
try {
debug('capture invoked');
const resType = 'image/png';
const imgData = await chrome.captureScreenshotAsStream(request.params.url, { outputType: 'png', metrics: BasicScreenMetrics })
if (request.query.thumbnail) {
const [width, height] = request.query.thumbnail.split(",").map(v => parseInt(v));
return reply(chrome.resizePng(imgData, { width, height })).type(resType);
}
else return reply(imgData).type(resType);
} catch (error) {
reply(error);
}
};

// POST endpoint
server.route({
method: 'POST',
path: '/screenshots/actions/capture',
config: captureConfig
});

// GET configuration
const thumbnailConfig = {
handler: captureThumbnailHandler,
validate: {
params: {
url: Joi.string().uri({
scheme: ['http', 'https']
}).required()
},
query: {
thumbnail: Joi.string().default('160,100')
}
}
}
// GET endpoint
server.route({
method: 'GET',
path: '/screenshots/{url}',
config: thumbnailConfig
});

server.on('stop', function () {
console.log('closing server');
});

// Start the server
server.start((err) => {
if (err) {
Expand Down
4 changes: 0 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,10 +80,6 @@ export class HandsfreeChrome {
const writeStream = fs.createWriteStream(`${absFilePath}.png`, { encoding: 'base64' });
const pngReadStream = await this.captureScreenshotAsStream(url, { outputType: 'png', metrics: options.metrics });
if (options.thumbnail) {
/*
const resizer = sharp();
resizer.resize(options.thumbnail.width, options.thumbnail.height).png();
*/
(await this.resizePng(pngReadStream, options.thumbnail)).pipe(writeStream);
}
else pngReadStream.pipe(writeStream);
Expand Down
59 changes: 54 additions & 5 deletions test/api.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ const should = chai.should();
const Hapi = require('hapi');
const request = require('supertest')
const api = require('../dist/api');
const querystring = require('querystring');
const server = api.server;


Expand All @@ -18,7 +19,8 @@ describe('Test API', function () {
});
}

describe('Calling /screenshots/actions/capture for a PNG', function () {
// POST
describe('Calling POST /screenshots/actions/capture for a PNG', function () {
it('for a valid URL should return 200 OK with an image/png data stream', function (done) {
request(server.listener)
.post('/screenshots/actions/capture')
Expand Down Expand Up @@ -92,14 +94,61 @@ describe('Test API', function () {
}
});
});

after('close server', async function () {
return await api.stop();
});

// GET
describe('Calling GET /screenshots/{url}', function () {
it('for a valid URL should return 200 OK with an image/png data stream', function (done) {
const url = `/screenshots/${querystring.escape('https://en.wikipedia.org/wiki/Software_bug')}`;
request(server.listener)
.get(url)
.expect(200)
.expect('Content-Type', /png/)
.buffer()
.parse(binaryParser)
.end(function (err, res) {
if (err) done(err);
else {
res.body.should.be.ok;
done();
}
});
});
it('for a valid URL request should return 200 OK with an image/png data stream', function (done) {
const url = 'https://www.vodafone.com';
request(server.listener)
.get(`/screenshots/${querystring.escape(url)}?thumbnail=160,100`)
.expect(200)
.expect('Content-Type', /png/)
.buffer()
.parse(binaryParser)
.end(function (err, res) {
if (err) done(err);
else {
res.body.should.be.ok;
done();
}
});
});
it.skip('for a not valid URL should return an error', function (done) {
const url = 'https://en.vvc.en.vvc';
request(server.listener)
.get(`/screenshots/${encodeURI(url)}?thumbnail=160,100`)
.expect(500)
.end(function (err, res) {
if (err) done(err);
else {
done();
}
});
});
});
after('close server', async function () {
return await api.stop();
});

});





0 comments on commit 1bf3612

Please sign in to comment.