Skip to content

Commit

Permalink
Merge pull request prisma-archive#3 from yusinto/file-proxy-yus
Browse files Browse the repository at this point in the history
Yus pr changes for encrypted-file-proxy
  • Loading branch information
yusinto authored Jun 26, 2017
2 parents c1d3064 + 84d8d8b commit 7222806
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 39 deletions.
2 changes: 1 addition & 1 deletion file-proxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ After running this command, `wt-cli` will return the url of your webtask. Using
Your webtask is now deployed! You can upload a file using any tool that support `multipart/form-data`, like Postman, or the command-line tool `curl`:

```sh
curl -X POST "<webtask endpoint url>/__GRAPHCOOL_PROJECT_ID__" -F "[email protected];filename=small.png"
curl -X POST '<webtask endpoint url>/__GRAPHCOOL_PROJECT_ID__' -F '[email protected];filename=small.png'
```

This uploads the local file `small-logo.png` with the new name `small.png`. The response should look something like this:
Expand Down
68 changes: 30 additions & 38 deletions file-proxy/encrypted-file-proxy.js
Original file line number Diff line number Diff line change
@@ -1,85 +1,77 @@
"use latest"
'use latest'

import Webtask from 'webtask-tools';
import express from 'express';
import crypto from 'crypto';
import multiparty from 'multiparty';
import formData from 'form-data';
import request from 'request';
import { request as gqlRequest } from 'graphql-request';

var app = express();
const app = express();

// The upload endpoint
app.post('/:projectid', (req, res) => {
app.post('/:projectId', (req, res) => {
const webtaskName = req.originalUrl.split('/')[1];
const projectId = req.params.projectId;
const graphCoolFileEndpoint = `https://api.graph.cool/file/v1/${projectId}`;
const graphCoolSimpleEndpoint = `https://api.graph.cool/simple/v1/${projectId}`;

// We set up a new multiparty form to process our request later on
var form = new multiparty.Form();
const form = new multiparty.Form();

// Multiparty generates a 'part' event for every file in the request
// This implementation assumes a single file is posted
form.on('part', function(part) {
form.on('part', part => {

// This is the encryption method. The password used for encryption is taken from a secrets
// Warning: this is *NOT* production ready encryption, but a simplified example
const cipher = crypto.createCipher('aes256', req.webtaskContext.secrets.FILE_ENC_PASSWORD);

// We construct a new form for posting to the actual Graphcool File API
var formdata = new formData();
const formdata = new formData();
// To reduce memory footprint for large file uploads, we use streaming
formdata.append("data", part.pipe(cipher), { filename: part.filename, contentType: part["content-type"] });
formdata.append('data', part.pipe(cipher), {filename: part.filename, contentType: part['content-type']});

// Post the constructed form to the Graphcool File API
request.post(`https://api.graph.cool/file/v1/${req.params.projectid}`,
request.post(graphCoolFileEndpoint,
{
headers: { "transfer-encoding": "chunked" },
headers: {'transfer-encoding': 'chunked'},
_form: formdata
}, (err, resp, body) => {
var result = JSON.parse(body);
const result = JSON.parse(body);

// The File API has created a File node. We need to update the URL to
// point to our own endpoint. Unfortunately, we can't, so we use a new
// field on the File Type to store our URL.
request.post(
{
url: `https://api.graph.cool/simple/v1/${req.params.projectid}`,
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
query: `
mutation {
updateFile (id: "${result.id}",
newUrl: "${result.url.replace('files.graph.cool', req.headers.host + '/' + webtaskName)}")
{
name
size
url
newUrl
id
contentType
}
}
`
})
},
(err,resp,body) => {
// Return the HTTP status code and body to the client, just like the 'normal' File API.
res.status(resp.statusCode).send(JSON.parse(body).data.updateFile);
});
const query = `
mutation updateFile($id: ID!, $newUrl: String!) {
updateFile (id: $id, newUrl: $newUrl)
{ name size url newUrl id contentType }
}`;

const variables = {
id: result.id,
newUrl: result.url.replace('files.graph.cool', `${req.headers.host}/${webtaskName}`)
};

gqlRequest(graphCoolSimpleEndpoint, query, variables)
.then(data => res.status(200).send(data.updateFile));
});
});
});

// Let multiparty parse the incoming request
form.parse(req);
});

// The download endpoint
app.get('/:projectid/:fileid', (req, res) => {
app.get('/:projectId/:fileId', (req, res) => {

// The decryption method, using the same secret password
const decipher = crypto.createDecipher('aes256', req.webtaskContext.secrets.FILE_ENC_PASSWORD);

// The request to the actual file
var resource = request.get(`https://files.graph.cool/${req.params.projectid}/${req.params.fileid}`);
const resource = request.get(`https://files.graph.cool/${req.params.projectId}/${req.params.fileId}`);

// As soon as we get a response, we copy the headers
// Content-length is removed, because the decrypted file does not have the same length
Expand Down
4 changes: 4 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1


0 comments on commit 7222806

Please sign in to comment.