diff --git a/docs/api.md b/docs/api.md index 70046e4d..65316ea5 100644 --- a/docs/api.md +++ b/docs/api.md @@ -85,7 +85,7 @@ If `opts` is specified, then the default options (shown below) will be overridde ```js { - announce: [], // Torrent trackers to use (added to list in .torrent or magnet uri) + announce: [String], // Torrent trackers to use (added to list in .torrent or magnet uri) getAnnounceOpts: Function, // Custom callback to allow sending extra parameters to the tracker maxWebConns: Number, // Max number of simultaneous connections per web seed [default=4] path: String, // Folder to download files to (default=`/tmp/webtorrent/`) @@ -316,13 +316,19 @@ Deprioritizes a range of previously selected pieces. Marks a range of pieces as critical priority to be downloaded ASAP. From `start` to `end` (both inclusive). -## `torrent.createServer([requestListener])` +## `torrent.createServer([opts])` Create an http server to serve the contents of this torrent, dynamically fetching the needed torrent pieces to satisfy http requests. Range requests are supported. Returns an `http.Server` instance (got from calling `http.createServer`). If -`requestListener` is specified, it is added to the 'request' event. +`opts` is specified, it can have the following properties: + +```js +{ + origin: String // Allow requests from specific origin. `false` for same-origin. [default: '*'] +} +``` Visiting the root of the server `/` will show a list of links to individual files. Access individual files at `/` where `` is the index in the `torrent.files` array diff --git a/lib/server.js b/lib/server.js index af1665d7..be45ddc1 100644 --- a/lib/server.js +++ b/lib/server.js @@ -7,8 +7,10 @@ var pump = require('pump') var rangeParser = require('range-parser') var url = require('url') -function Server (torrent, requestListener) { - var server = http.createServer(requestListener) +function Server (torrent, opts) { + var server = http.createServer() + if (!opts) opts = {} + if (!opts.origin) opts.origin = '*' // allow all origins by default var sockets = [] var pendingReady = [] @@ -41,6 +43,21 @@ function Server (torrent, requestListener) { else server.close(cb) } + function isOriginAllowed (req) { + // When `origin` option is `false`, deny all cross-origin requests + if (opts.origin === false) return false + + // Requests without an 'Origin' header are not actually cross-origin, so just + // deny them + if (req.headers.origin == null) return false + + // The user allowed all origins + if (opts.origin === '*') return true + + // Allow requests where the 'Origin' header matches the `opts.origin` setting + return req.headers.origin === opts.origin + } + function onConnection (socket) { socket.setTimeout(36000000) sockets.push(socket) @@ -56,9 +73,9 @@ function Server (torrent, requestListener) { return serve404Page() } - // Allow CORS requests to read responses - if (req.headers.origin) { - res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*') + // Allow cross-origin requests (CORS) + if (isOriginAllowed(req)) { + res.setHeader('Access-Control-Allow-Origin', req.headers.origin) } // Prevent browser mime-type sniffing @@ -68,7 +85,8 @@ function Server (torrent, requestListener) { // by responding to the OPTIONS preflight request with the specified // origin and requested headers. if (req.method === 'OPTIONS') { - return serveOptionsRequest() + if (isOriginAllowed(req)) return serveOptionsRequest() + else return serveMethodNotAllowed() } if (req.method === 'GET' || req.method === 'HEAD') {