Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Memory-based store to simplify things
- Loading branch information
Showing
6 changed files
with
185 additions
and
163 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
schema = require("json-schema") | ||
mime = require("mime") | ||
_ = require("underscore")._ | ||
|
||
module.exports = (store) -> | ||
load: (req, id, cb) -> | ||
# Fetch the plunk (async) | ||
store.fetch id, (err, plunk) -> | ||
return cb(err) if err | ||
|
||
# Although not necessarily the 'appropriate' place to put this check for | ||
# a token passed in the query string or in the Authorization header. | ||
if req.query.token and req.query.token == plunk.token | ||
req.authorized = true | ||
else if auth = req.header("Authorization") | ||
[token] = auth.match(/^token (\S+)$/i) | ||
|
||
if token and token == plunk.token | ||
req.authorized = true | ||
|
||
cb(null, plunk) | ||
|
||
|
||
create: (req, res, next) -> | ||
json = _.clone(req.body) | ||
|
||
# Validate the json against the json-schema | ||
{valid, errors} = schema.validate(json, require("../lib/schema/create")) | ||
|
||
# Trigger an appropriate error if validation fails | ||
unless valid then return next({number: 422, message: "Validation failed", errors: errors }) | ||
|
||
# Files can be provided as a hash of filename => contents or filename => file descriptor | ||
# This code normalizes them to the latter format | ||
_.each json.files, (file, filename) -> | ||
if _.isString(file) then file = { content: file } | ||
file.filename = filename | ||
file.mime ||= mime.lookup(file.filename) | ||
file.encoding ||= mime.charsets.lookup(file.mime) | ||
|
||
json.files[filename] = _.clone(file) | ||
|
||
store.create json, (err, plunk) -> | ||
if err then next(err) | ||
else res.json(plunk) | ||
|
||
show: (req, res, next) -> | ||
delete req.plunk.token unless req.authorized | ||
|
||
res.json(req.plunk) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,49 @@ | ||
express = require("express") | ||
resource = require("express-resource") | ||
|
||
config = require("./config") | ||
|
||
app = module.exports = express.createServer() | ||
|
||
app.configure -> | ||
app.use express.logger() | ||
app.use express.methodOverride() | ||
app.use express.bodyParser() | ||
|
||
|
||
{Store} = require("./lib/stores/redis") | ||
{Plunks, Plunk} = require("./lib/plunks") | ||
|
||
store = new Store(config.redis) | ||
|
||
Plunk::sync = store.sync | ||
Plunks::sync = store.sync | ||
|
||
plunks = new Plunks | ||
|
||
|
||
app.post "/api/v1/plunks", (req, res) -> | ||
plunks.create req.body, | ||
success: (model) -> res.json model.toJSON() | ||
error: (model, err) -> res.send err, 400 | ||
|
||
app.get "/api/v1/plunks/:id", (req, res) -> | ||
plunk = new Plunk(id: req.param("id")) | ||
plunk.fetch | ||
success: (model) -> res.json model.toJSON() | ||
error: (model, err) -> res.send err, 400 | ||
|
||
|
||
|
||
|
||
app.get "/:id/", (req, res) -> | ||
plunk = new Plunk(id: req.param("id")) | ||
plunk.fetch | ||
success: (model) -> | ||
filename = model.get("index") | ||
file = model.files.get(filename) | ||
|
||
if file then res.send file.get("content"), { "Content-Type": file.get("mime") } | ||
else res.send "#{filename} not found in plunk", 404 | ||
error: (err) -> | ||
res.send "No such plunk", 404 | ||
|
||
app.get "/:id", (req, res) -> | ||
res.redirect(req.url + "/", 301) | ||
|
||
app.get "/:id/:filename", (req, res) -> | ||
plunk = new Plunk(id: req.param("id")) | ||
plunk.fetch | ||
success: (model) -> | ||
filename = req.param("filename") | ||
file = model.files.get(req.param("filename")) | ||
|
||
if file then res.send file.get("content"), { "Content-Type": file.get("mime") } | ||
else res.send "#{filename} not found in plunk", 404 | ||
error: (err) -> | ||
res.send "No such plunk", 404 | ||
|
||
|
||
|
||
app.get "/", (req, res) -> | ||
res.send "Welcome to Plunk" | ||
app.use express.bodyParser() | ||
|
||
{Store} = require("./lib/stores/memory") | ||
store = new Store(config) | ||
|
||
# Expose the public api for plunks | ||
app.resource "api/v1/plunks", require("./api/plunks")(store) | ||
|
||
|
||
# Serve up a plunk | ||
app.get "/:id/", (req, res, next) -> | ||
store.fetch req.params.id, (err, plunk) -> | ||
return res.send(500) if err | ||
return res.send(404) unless plunk | ||
|
||
file = plunk.files[plunk.index] | ||
|
||
return res.send(404) unless file | ||
return res.send(file.content, {"Content-Type": file.mime}) | ||
app.get "/:id", (req, res) -> res.redirect("/#{req.params.id}/", 301) | ||
|
||
# Serve a specific file in a plunk | ||
app.get "/:id/*", (req, res, next) -> | ||
store.fetch req.params.id, (err, plunk) -> | ||
return res.send(500) if err | ||
return res.send(404) unless plunk | ||
|
||
file = plunk.files[req.params[0]] | ||
|
||
return res.send(404) unless file | ||
return res.send(file.content, {"Content-Type": file.mime}) | ||
|
||
# Handle errors | ||
app.error (err, req, res, next) -> | ||
body = {} | ||
if err.message then body.message = err.message | ||
if err.errors then body.errors = err.errors | ||
|
||
res.json body, err.number or 400 |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
module.exports = | ||
type: "object" | ||
properties: | ||
description: | ||
type: "string" | ||
index: | ||
type: "string" | ||
default: "index.html" | ||
files: | ||
required: true | ||
type: [ | ||
type: "array" | ||
minItems: 1 | ||
items: | ||
type: "object" | ||
properties: | ||
filename: | ||
type: "string" | ||
required: true | ||
content: | ||
type: "string" | ||
required: true | ||
mime: | ||
type: "string" | ||
encoding: | ||
type: "string" | ||
, | ||
type: "object" | ||
minProperties: 1 | ||
items: | ||
type: "string" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
cromag = require("cromag") | ||
_ = require("underscore")._ | ||
|
||
|
||
# From connect/utils.js | ||
uid = (len = 6) -> | ||
keyspace = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" | ||
key = "" | ||
|
||
while len-- > 0 | ||
key += keyspace.charAt(Math.floor(Math.random() * keyspace.length)) | ||
|
||
key | ||
|
||
deepClone = (obj) -> | ||
if _.isArray(obj) | ||
clone = _.map obj, (elem) -> deepClone(elem) | ||
else if typeof obj == 'object' | ||
clone = {} | ||
|
||
_.each obj, (val, key) -> clone[key] = deepClone(val) | ||
else | ||
clone = obj | ||
|
||
clone | ||
|
||
class exports.Store | ||
constructor: ({@ttl, @server} = {ttl: 60 * 60 * 24 * 2, server: ""})-> | ||
@plunks = {} | ||
@timeouts = {} | ||
|
||
createDestructor: (id) -> | ||
self = @ | ||
-> | ||
delete self.plunks[id] | ||
delete self.timeouts[id] | ||
|
||
exists: (uid) -> !!@plunks[uid] | ||
create: (json, cb) -> | ||
json.id = uid(6) | ||
json.token = uid(16) | ||
json.ttl = @ttl | ||
json.expires = new cromag(cromag.now() + json.ttl * 1000).toISOString() | ||
json.url = "#{@server}/#{json.id}/" | ||
|
||
json.id = uid(6) while @exists(json.id) | ||
|
||
@plunks[json.id] = json | ||
@timeouts[json.id] = setTimeout(@createDestructor(json.id), json.ttl * 1000) | ||
|
||
cb(null, json) | ||
|
||
fetch: (id, cb) -> | ||
if plunk = @plunks[id] | ||
plunk = deepClone(plunk) | ||
plunk.ttl = Math.floor((cromag.parse(plunk.expires) - cromag.now()) / 1000) | ||
|
||
return cb(null, plunk) |
Oops, something went wrong.