{"action":"created","comment":{"url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/comments/215286156","pull_request_review_id":152515116,"id":215286156,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxNTI4NjE1Ng==","diff_hunk":"@@ -1,55 +1,184 @@\n 'use strict';\n \n+// Bootstrap and config\n const AWS = require('aws-sdk');\n+const Sharp = require('sharp');\n+\n+\n const S3 = new AWS.S3({\n   signatureVersion: 'v4',\n });\n-const Sharp = require('sharp');\n \n-const BUCKET = process.env.BUCKET;\n-const URL = process.env.URL;\n+const { BUCKET, URL } = process.env;\n const ALLOWED_DIMENSIONS = new Set();\n \n if (process.env.ALLOWED_DIMENSIONS) {\n   const dimensions = process.env.ALLOWED_DIMENSIONS.split(/\\s*,\\s*/);\n-  dimensions.forEach((dimension) => ALLOWED_DIMENSIONS.add(dimension));\n+  dimensions.forEach(dimension => ALLOWED_DIMENSIONS.add(dimension));\n+}\n+\n+const contentTypeFormatMap = {\n+  'image/jpeg': 'jpeg',\n+  'image/png': 'png',\n+  'image/webp': 'webp',\n+  'image/tiff': 'tiff',\n+};\n+\n+const contentTypeOptionsMap = {\n+  // Each output format has lots of options\n+  // http://sharp.dimens.io/en/stable/api-output/#parameters_3\n+  'image/jpeg': { quality: 90 },\n+  'image/png': {},\n+  'image/webp': { quality: 90 },\n+  'image/tiff': { compression: 'lzw' },\n+};\n+\n+\n+// Error response definitions\n+function invalidPathResponse() {\n+  return {\n+    statusCode: '400',\n+    headers: { 'Content-Type': 'application/json' },\n+    body: JSON.stringify({\n+      code: 'INVALID_PATH',\n+      message: 'Path did not match expected format.',\n+    }),\n+  };\n }\n \n-exports.handler = function(event, context, callback) {\n-  const key = event.queryStringParameters.key;\n-  const match = key.match(/((\\d+)x(\\d+))\\/(.*)/);\n-  const dimensions = match[1];\n-  const width = parseInt(match[2], 10);\n-  const height = parseInt(match[3], 10);\n-  const originalKey = match[4];\n-\n-  if(ALLOWED_DIMENSIONS.size > 0 && !ALLOWED_DIMENSIONS.has(dimensions)) {\n-     callback(null, {\n-      statusCode: '403',\n-      headers: {},\n-      body: '',\n-    });\n+function invalidDimensionsResponse() {\n+  const dimensions = Array.from(ALLOWED_DIMENSIONS).join(', ');\n+  return {\n+    statusCode: '400',\n+    headers: { 'Content-Type': 'application/json' },\n+    body: JSON.stringify({\n+      code: 'INVALID_DIMENSIONS',\n+      message: `Allowed dimensions: ${dimensions}`,\n+    }),\n+  };\n+}\n+\n+function unsupportedFormatResponse() {\n+  const contentTypes = Object.keys(contentTypeFormatMap).join(', ');\n+  return {\n+    statusCode: '400',\n+    headers: { 'Content-Type': 'application/json' },\n+    body: JSON.stringify({\n+      code: 'UNSUPPORTED_FORMAT',\n+      message: `Supported content types: ${contentTypes}`,\n+    }),\n+  };\n+}\n+\n+function notFoundResponse(bucket, key) {\n+  return {\n+    statusCode: '404',\n+    headers: { 'Content-Type': 'application/json' },\n+    body: JSON.stringify({\n+      code: 'NOT_FOUND',\n+      message: `Asset not found in bucket ${bucket} with key ${key}`,\n+    }),\n+  };\n+}\n+\n+// Success response definition\n+\n+\n+// Main handler called by API gateway\n+exports.handler = async function handler(event, context, callback) {\n+  const { key } = event.queryStringParameters;\n+  // example: 'resize/75c06d3b-4342-4ab8-aa37-b1f01d654ac1/private/avatar/50x60-img123'\n+\n+  const fullPath = key.split('/');\n+  // example: ['resize','75c06d3b-4342-4ab8-aa37-b1f01d654ac1','private','avatar','50x60-img123']\n+  if (fullPath.length < 2 || fullPath[0] !== 'resize') {\n+    // has to start with 'resize' and end with the asset name, can have more paths in between.\n+    callback(null, invalidPathResponse());\n+    return;\n+  }\n+\n+  const middlePath = fullPath.slice(1, fullPath.length - 1).join('/');\n+  // example '75c06d3b-4342-4ab8-aa37-b1f01d654ac1/private/avatar'\n+\n+  const dimsAndAssetName = fullPath[fullPath.length - 1]; // example: '50x60-img123'\n+\n+  const match = dimsAndAssetName.match(/((\\d+)x(\\d+))-(.+)/);\n+  if (match === null) {\n+    callback(null, invalidPathResponse());\n     return;\n   }\n+  const dimensions = match[1]; // example: '50x60'\n+  const width = parseInt(match[2], 10); // example: 50\n+  const height = parseInt(match[3], 10); // example: 60\n+  const assetName = match[4]; // example: 'img123'\n \n-  S3.getObject({Bucket: BUCKET, Key: originalKey}).promise()\n-    .then(data => Sharp(data.Body)\n+  const fullResKey = `assets/${middlePath}/${assetName}`;\n+  // example 'assets/75c06d3b-4342-4ab8-aa37-b1f01d654ac1/private/avatar/img123'\n+\n+  // If we are restricting the allowable dimensions, make sure the request meets that.\n+  if (ALLOWED_DIMENSIONS.size > 0 && !ALLOWED_DIMENSIONS.has(dimensions)) {\n+    callback(null, invalidDimensionsResponse());\n+    return;\n+  }\n+\n+\n+  // Get the full sized image out of S3\n+  let data;\n+  try {\n+    data = await S3.getObject({ Bucket: BUCKET, Key: fullResKey }).promise();\n+  } catch (e) {\n+    // Check for not found error\n+    if (e.code === 'NoSuchKey') {\n+      callback(null, notFoundResponse(BUCKET, fullResKey));\n+      return;\n+    }\n+    callback(e);\n+    return;\n+  }\n+  // Check that the content type of the image is supported.\n+  if (!(data.ContentType in contentTypeFormatMap)) {\n+    callback(null, unsupportedFormatResponse());\n+    return;\n+  }\n+\n+\n+  // Add a \"resized-from\" property to the metadata\n+  const metadata = data.Metadata;\n+  metadata['resized-from'] = fullResKey;\n+\n+\n+  // Resize it with Sharp\n+  let buffer;\n+  try {\n+    buffer = await Sharp(data.Body)\n       .resize(width, height)\n-      .toFormat('png')\n-      .toBuffer()\n-    )\n-    .then(buffer => S3.putObject({\n-        Body: buffer,\n-        Bucket: BUCKET,\n-        ContentType: 'image/png',\n-        Key: key,\n-      }).promise()\n-    )\n-    .then(() => callback(null, {\n-        statusCode: '301',\n-        headers: {'location': `${URL}/${key}`},\n-        body: '',\n-      })\n-    )\n-    .catch(err => callback(err))\n-}\n+      .toFormat(contentTypeFormatMap[data.ContentType], contentTypeOptionsMap[data.ContentType])\n+      .toBuffer();\n+  } catch (e) {\n+    callback(e);\n+    return;\n+  }\n+\n+\n+  // Save the resized image to S3 for retrieving later.\n+  try {\n+    await S3.putObject({\n+      Body: buffer,\n+      Bucket: BUCKET,\n+      ContentType: data.ContentType, // use the original content type\n+      Metadata: metadata, // copy the original's metadata.\n+      Key: key, // gets saved at the path that was originally requested.\n+    }).promise();\n+  } catch (e) {\n+    callback(e);\n+    return;\n+  }\n+\n+\n+  // Redirect to the newly created image\n+  callback(null, {\n+    statusCode: '301',\n+    headers: { location: `${URL}/${key}` },","path":"lambda/index.js","position":219,"original_position":219,"commit_id":"2aeb4c350bcc66a13b9f50e46455d5c7589774f1","original_commit_id":"2aeb4c350bcc66a13b9f50e46455d5c7589774f1","user":{"login":"jcoplonsdc","id":36864760,"node_id":"MDQ6VXNlcjM2ODY0NzYw","avatar_url":"https://avatars0.githubusercontent.com/u/36864760?v=4","gravatar_id":"","url":"https://api.github.com/users/jcoplonsdc","html_url":"https://github.com/jcoplonsdc","followers_url":"https://api.github.com/users/jcoplonsdc/followers","following_url":"https://api.github.com/users/jcoplonsdc/following{/other_user}","gists_url":"https://api.github.com/users/jcoplonsdc/gists{/gist_id}","starred_url":"https://api.github.com/users/jcoplonsdc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jcoplonsdc/subscriptions","organizations_url":"https://api.github.com/users/jcoplonsdc/orgs","repos_url":"https://api.github.com/users/jcoplonsdc/repos","events_url":"https://api.github.com/users/jcoplonsdc/events{/privacy}","received_events_url":"https://api.github.com/users/jcoplonsdc/received_events","type":"User","site_admin":false},"body":"Oy... and one other consideration I should have noted in the story is that there is an intent to have a gateway in front of the s3 bucket so we can control headers and error responses from S3 so we'll need to be able to change the domain of the bucket on the response.","created_at":"2018-09-05T14:11:26Z","updated_at":"2018-09-05T14:11:26Z","html_url":"https://github.com/CamelotVG/serverless-image-resizing/pull/1#discussion_r215286156","pull_request_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1","author_association":"COLLABORATOR","_links":{"self":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/comments/215286156"},"html":{"href":"https://github.com/CamelotVG/serverless-image-resizing/pull/1#discussion_r215286156"},"pull_request":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1"}},"in_reply_to_id":215283976},"pull_request":{"url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1","id":213098838,"node_id":"MDExOlB1bGxSZXF1ZXN0MjEzMDk4ODM4","html_url":"https://github.com/CamelotVG/serverless-image-resizing/pull/1","diff_url":"https://github.com/CamelotVG/serverless-image-resizing/pull/1.diff","patch_url":"https://github.com/CamelotVG/serverless-image-resizing/pull/1.patch","issue_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/1","number":1,"state":"open","locked":false,"title":"Feature/eng-8206 image resize functionality","user":{"login":"devgr","id":6100005,"node_id":"MDQ6VXNlcjYxMDAwMDU=","avatar_url":"https://avatars2.githubusercontent.com/u/6100005?v=4","gravatar_id":"","url":"https://api.github.com/users/devgr","html_url":"https://github.com/devgr","followers_url":"https://api.github.com/users/devgr/followers","following_url":"https://api.github.com/users/devgr/following{/other_user}","gists_url":"https://api.github.com/users/devgr/gists{/gist_id}","starred_url":"https://api.github.com/users/devgr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/devgr/subscriptions","organizations_url":"https://api.github.com/users/devgr/orgs","repos_url":"https://api.github.com/users/devgr/repos","events_url":"https://api.github.com/users/devgr/events{/privacy}","received_events_url":"https://api.github.com/users/devgr/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-09-04T20:46:27Z","updated_at":"2018-09-05T14:11:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"dd9b46d482d34df61c5282da57378a9d81407a24","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1/commits","review_comments_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1/comments","review_comment_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/comments{/number}","comments_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/1/comments","statuses_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/statuses/2aeb4c350bcc66a13b9f50e46455d5c7589774f1","head":{"label":"CamelotVG:feature/eng-8206-image-resize-functionality","ref":"feature/eng-8206-image-resize-functionality","sha":"2aeb4c350bcc66a13b9f50e46455d5c7589774f1","user":{"login":"CamelotVG","id":8368145,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgzNjgxNDU=","avatar_url":"https://avatars0.githubusercontent.com/u/8368145?v=4","gravatar_id":"","url":"https://api.github.com/users/CamelotVG","html_url":"https://github.com/CamelotVG","followers_url":"https://api.github.com/users/CamelotVG/followers","following_url":"https://api.github.com/users/CamelotVG/following{/other_user}","gists_url":"https://api.github.com/users/CamelotVG/gists{/gist_id}","starred_url":"https://api.github.com/users/CamelotVG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CamelotVG/subscriptions","organizations_url":"https://api.github.com/users/CamelotVG/orgs","repos_url":"https://api.github.com/users/CamelotVG/repos","events_url":"https://api.github.com/users/CamelotVG/events{/privacy}","received_events_url":"https://api.github.com/users/CamelotVG/received_events","type":"Organization","site_admin":false},"repo":{"id":140859460,"node_id":"MDEwOlJlcG9zaXRvcnkxNDA4NTk0NjA=","name":"serverless-image-resizing","full_name":"CamelotVG/serverless-image-resizing","owner":{"login":"CamelotVG","id":8368145,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgzNjgxNDU=","avatar_url":"https://avatars0.githubusercontent.com/u/8368145?v=4","gravatar_id":"","url":"https://api.github.com/users/CamelotVG","html_url":"https://github.com/CamelotVG","followers_url":"https://api.github.com/users/CamelotVG/followers","following_url":"https://api.github.com/users/CamelotVG/following{/other_user}","gists_url":"https://api.github.com/users/CamelotVG/gists{/gist_id}","starred_url":"https://api.github.com/users/CamelotVG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CamelotVG/subscriptions","organizations_url":"https://api.github.com/users/CamelotVG/orgs","repos_url":"https://api.github.com/users/CamelotVG/repos","events_url":"https://api.github.com/users/CamelotVG/events{/privacy}","received_events_url":"https://api.github.com/users/CamelotVG/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CamelotVG/serverless-image-resizing","description":"Node.js package to resize images on-the-fly using Amazon API Gateway, AWS Lambda, and Amazon S3. ","fork":true,"url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing","forks_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/forks","keys_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/teams","hooks_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/hooks","issue_events_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/events{/number}","events_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/events","assignees_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/assignees{/user}","branches_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/branches{/branch}","tags_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/tags","blobs_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/refs{/sha}","trees_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/statuses/{sha}","languages_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/languages","stargazers_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/stargazers","contributors_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/contributors","subscribers_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/subscribers","subscription_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/subscription","commits_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/commits{/sha}","git_commits_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/commits{/sha}","comments_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/comments{/number}","issue_comment_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/comments{/number}","contents_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/contents/{+path}","compare_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/merges","archive_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/downloads","issues_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues{/number}","pulls_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls{/number}","milestones_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/milestones{/number}","notifications_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/labels{/name}","releases_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/releases{/id}","deployments_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/deployments","created_at":"2018-07-13T14:50:03Z","updated_at":"2018-08-28T19:36:51Z","pushed_at":"2018-09-04T21:09:25Z","git_url":"git://github.com/CamelotVG/serverless-image-resizing.git","ssh_url":"git@github.com:CamelotVG/serverless-image-resizing.git","clone_url":"https://github.com/CamelotVG/serverless-image-resizing.git","svn_url":"https://github.com/CamelotVG/serverless-image-resizing","homepage":"","size":44250,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"base":{"label":"CamelotVG:master","ref":"master","sha":"2e8a430e06770fc51b46baa5f4f8b5e5caeb4b2f","user":{"login":"CamelotVG","id":8368145,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgzNjgxNDU=","avatar_url":"https://avatars0.githubusercontent.com/u/8368145?v=4","gravatar_id":"","url":"https://api.github.com/users/CamelotVG","html_url":"https://github.com/CamelotVG","followers_url":"https://api.github.com/users/CamelotVG/followers","following_url":"https://api.github.com/users/CamelotVG/following{/other_user}","gists_url":"https://api.github.com/users/CamelotVG/gists{/gist_id}","starred_url":"https://api.github.com/users/CamelotVG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CamelotVG/subscriptions","organizations_url":"https://api.github.com/users/CamelotVG/orgs","repos_url":"https://api.github.com/users/CamelotVG/repos","events_url":"https://api.github.com/users/CamelotVG/events{/privacy}","received_events_url":"https://api.github.com/users/CamelotVG/received_events","type":"Organization","site_admin":false},"repo":{"id":140859460,"node_id":"MDEwOlJlcG9zaXRvcnkxNDA4NTk0NjA=","name":"serverless-image-resizing","full_name":"CamelotVG/serverless-image-resizing","owner":{"login":"CamelotVG","id":8368145,"node_id":"MDEyOk9yZ2FuaXphdGlvbjgzNjgxNDU=","avatar_url":"https://avatars0.githubusercontent.com/u/8368145?v=4","gravatar_id":"","url":"https://api.github.com/users/CamelotVG","html_url":"https://github.com/CamelotVG","followers_url":"https://api.github.com/users/CamelotVG/followers","following_url":"https://api.github.com/users/CamelotVG/following{/other_user}","gists_url":"https://api.github.com/users/CamelotVG/gists{/gist_id}","starred_url":"https://api.github.com/users/CamelotVG/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CamelotVG/subscriptions","organizations_url":"https://api.github.com/users/CamelotVG/orgs","repos_url":"https://api.github.com/users/CamelotVG/repos","events_url":"https://api.github.com/users/CamelotVG/events{/privacy}","received_events_url":"https://api.github.com/users/CamelotVG/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/CamelotVG/serverless-image-resizing","description":"Node.js package to resize images on-the-fly using Amazon API Gateway, AWS Lambda, and Amazon S3. ","fork":true,"url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing","forks_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/forks","keys_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/keys{/key_id}","collaborators_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/teams","hooks_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/hooks","issue_events_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/events{/number}","events_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/events","assignees_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/assignees{/user}","branches_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/branches{/branch}","tags_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/tags","blobs_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/refs{/sha}","trees_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/trees{/sha}","statuses_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/statuses/{sha}","languages_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/languages","stargazers_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/stargazers","contributors_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/contributors","subscribers_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/subscribers","subscription_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/subscription","commits_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/commits{/sha}","git_commits_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/git/commits{/sha}","comments_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/comments{/number}","issue_comment_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/comments{/number}","contents_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/contents/{+path}","compare_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/compare/{base}...{head}","merges_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/merges","archive_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/downloads","issues_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues{/number}","pulls_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls{/number}","milestones_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/milestones{/number}","notifications_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/labels{/name}","releases_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/releases{/id}","deployments_url":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/deployments","created_at":"2018-07-13T14:50:03Z","updated_at":"2018-08-28T19:36:51Z","pushed_at":"2018-09-04T21:09:25Z","git_url":"git://github.com/CamelotVG/serverless-image-resizing.git","ssh_url":"git@github.com:CamelotVG/serverless-image-resizing.git","clone_url":"https://github.com/CamelotVG/serverless-image-resizing.git","svn_url":"https://github.com/CamelotVG/serverless-image-resizing","homepage":"","size":44250,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":1,"license":{"key":"apache-2.0","name":"Apache License 2.0","spdx_id":"Apache-2.0","url":"https://api.github.com/licenses/apache-2.0","node_id":"MDc6TGljZW5zZTI="},"forks":0,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1"},"html":{"href":"https://github.com/CamelotVG/serverless-image-resizing/pull/1"},"issue":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/1"},"comments":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/CamelotVG/serverless-image-resizing/statuses/2aeb4c350bcc66a13b9f50e46455d5c7589774f1"}},"author_association":"NONE"}}
{"actor":{"display_login":"jcoplonsdc"}}