From 0444916c04c39bb27c1944f0e09219859ff5740c Mon Sep 17 00:00:00 2001 From: Rob McGuire-Dale Date: Fri, 9 Oct 2015 06:35:57 -0700 Subject: [PATCH 01/33] JS: Make comments file reference relative to server file --- server.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 1379adbb..f4f331ea 100644 --- a/server.js +++ b/server.js @@ -16,6 +16,8 @@ var express = require('express'); var bodyParser = require('body-parser'); var app = express(); +var COMMENTS_FILE = path.join(__dirname, 'comments.json'); + app.set('port', (process.env.PORT || 3000)); app.use('/', express.static(path.join(__dirname, 'public'))); @@ -23,17 +25,17 @@ app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); app.get('/api/comments', function(req, res) { - fs.readFile('comments.json', function(err, data) { + fs.readFile(COMMENTS_FILE, function(err, data) { res.setHeader('Cache-Control', 'no-cache'); res.json(JSON.parse(data)); }); }); app.post('/api/comments', function(req, res) { - fs.readFile('comments.json', function(err, data) { + fs.readFile(COMMENTS_FILE, function(err, data) { var comments = JSON.parse(data); comments.push(req.body); - fs.writeFile('comments.json', JSON.stringify(comments, null, 4), function(err) { + fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) { res.setHeader('Cache-Control', 'no-cache'); res.json(comments); }); From 8f4f0dbad9184114b743029837d996db729fc484 Mon Sep 17 00:00:00 2001 From: Rob McGuire-Dale Date: Fri, 9 Oct 2015 06:53:40 -0700 Subject: [PATCH 02/33] Add 'changining the port' section to the README --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 89ea4e77..f72917ef 100644 --- a/README.md +++ b/README.md @@ -55,3 +55,11 @@ algernon server.lua ``` And visit . Try opening multiple tabs! + +## Changing the port + +You can change the port number by setting the `$PORT` environment variable before invoking any of the scripts above, e.g., + +```sh +PORT=3001 node server.js +``` From 208e00fd909323f69be2cbad0c84c2f1336da9f6 Mon Sep 17 00:00:00 2001 From: David Farrell Date: Mon, 26 Oct 2015 14:47:44 -0400 Subject: [PATCH 03/33] Example web server in Perl --- README.md | 7 +++++++ server.pl | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 server.pl diff --git a/README.md b/README.md index f72917ef..44f65390 100644 --- a/README.md +++ b/README.md @@ -54,6 +54,13 @@ go get github.com/xyproto/algernon algernon server.lua ``` +### Perl + +```sh +cpan Mojolicious +perl server.pl +``` + And visit . Try opening multiple tabs! ## Changing the port diff --git a/server.pl b/server.pl new file mode 100644 index 00000000..ce1783e7 --- /dev/null +++ b/server.pl @@ -0,0 +1,34 @@ +# This file provided by Facebook is for non-commercial testing and evaluation +# purposes only. Facebook reserves all rights not expressly granted. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +use Mojolicious::Lite; +use Mojo::JSON qw(encode_json decode_json); + +app->static->paths->[0] = './public'; + +any '/' => sub { $_[0]->reply->static('index.html') }; + +any [qw(GET POST)] => '/api/comments' => sub { + my $self = shift; + my $comments = decode_json (do { local(@ARGV,$/) = 'comments.json';<> }); + + if ($self->req->method eq 'POST') + { + push @$comments, { + author => $self->param('author'), + text => $self->param('text'), + }; + open my $FILE, '>', 'comments.json'; + print $FILE encode_json($comments); + } + $self->render(json => $comments); +}; +my $port = $ENV{PORT} || 3000; +app->start('daemon', '-l', "http://*:$port"); From eec66b187aa48374a6f9e9e078b8e8f53845925f Mon Sep 17 00:00:00 2001 From: Chris Tsongas Date: Mon, 26 Oct 2015 22:03:41 +0100 Subject: [PATCH 04/33] Fix failure to roll back optimistic update after error --- public/scripts/example.js | 1 + 1 file changed, 1 insertion(+) diff --git a/public/scripts/example.js b/public/scripts/example.js index 7e7bf35d..2e0ee2a8 100644 --- a/public/scripts/example.js +++ b/public/scripts/example.js @@ -55,6 +55,7 @@ var CommentBox = React.createClass({ this.setState({data: data}); }.bind(this), error: function(xhr, status, err) { + this.setState({data: comments}); console.error(this.props.url, status, err.toString()); }.bind(this) }); From 2ddef372f1ed743471e21f1d5c610d7751b20d73 Mon Sep 17 00:00:00 2001 From: Varun Maudgalya Date: Mon, 2 Nov 2015 14:17:06 -0800 Subject: [PATCH 05/33] Added error handling --- server.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server.js b/server.js index f4f331ea..2946e370 100644 --- a/server.js +++ b/server.js @@ -26,6 +26,7 @@ app.use(bodyParser.urlencoded({extended: true})); app.get('/api/comments', function(req, res) { fs.readFile(COMMENTS_FILE, function(err, data) { + if (err) console.log(err); res.setHeader('Cache-Control', 'no-cache'); res.json(JSON.parse(data)); }); @@ -33,9 +34,11 @@ app.get('/api/comments', function(req, res) { app.post('/api/comments', function(req, res) { fs.readFile(COMMENTS_FILE, function(err, data) { + if (err) console.log(err); var comments = JSON.parse(data); comments.push(req.body); fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) { + if (err) console.log(err); res.setHeader('Cache-Control', 'no-cache'); res.json(comments); }); From 587268e6a2490afe2eb13f13ca359c29f6aa86a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 10 Nov 2015 15:34:13 -0800 Subject: [PATCH 06/33] Remove Lua server --- README.md | 8 -------- server.lua | 38 -------------------------------------- 2 files changed, 46 deletions(-) delete mode 100644 server.lua diff --git a/README.md b/README.md index 44f65390..72ce4462 100644 --- a/README.md +++ b/README.md @@ -46,14 +46,6 @@ php server.php go run server.go ``` -### Lua - -```sh -go get github.com/xyproto/algernon -# or brew install algernon -algernon server.lua -``` - ### Perl ```sh diff --git a/server.lua b/server.lua deleted file mode 100644 index 10df59fc..00000000 --- a/server.lua +++ /dev/null @@ -1,38 +0,0 @@ --- This file provided by Facebook is for non-commercial testing and evaluation --- purposes only. Facebook reserves all rights not expressly granted. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL --- FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN --- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION --- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - --- --- For use with Algernon / Lua --- --- Project page: https://github.com/xyproto/algernon --- Web page: http://algernon.roboticoverlords.org/ --- - -handle("/api/comments", function() - - -- Set the headers - content("application/javascript") - setheader("Cache-Control", "no-cache") - - -- Use a JSON file for the comments - comments = JFile("comments.json") - - -- Handle requests - if method() == "POST" then - -- Add the form data table to the JSON document - comments:add(ToJSON(formdata(), 4)) - end - - -- Return the contents of the JSON file - print(tostring(comments)) - -end) - -servedir("/", "public") From 485052b520447f00578ceab58875b3422adaf7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 10 Nov 2015 15:36:20 -0800 Subject: [PATCH 07/33] Remove Haskell server --- README.md | 9 ------- Server.hs | 62 ---------------------------------------------- react-scotty.cabal | 28 --------------------- 3 files changed, 99 deletions(-) delete mode 100644 Server.hs delete mode 100644 react-scotty.cabal diff --git a/README.md b/README.md index 72ce4462..4862f5df 100644 --- a/README.md +++ b/README.md @@ -22,15 +22,6 @@ pip install -r requirements.txt python server.py ``` -### Haskell - -```sh -cabal sandbox init -cabal install --only-dependencies -ghc Server.hs -./Server -``` - ### Ruby ```sh ruby server.rb diff --git a/Server.hs b/Server.hs deleted file mode 100644 index 9a5c747e..00000000 --- a/Server.hs +++ /dev/null @@ -1,62 +0,0 @@ --- This file provided by Facebook is for non-commercial testing and evaluation --- purposes only. Facebook reserves all rights not expressly granted. --- --- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL --- FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN --- ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION --- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE - -{-# LANGUAGE OverloadedStrings #-} - -module Main (main) where - -import Web.Scotty - -import Control.Monad (mzero) -import Control.Monad.Trans -import Network.Wai.Middleware.Static -import Network.Wai.Middleware.RequestLogger (logStdoutDev) -import Data.ByteString.Lazy (readFile, writeFile, fromStrict) -import qualified Data.ByteString as BS (readFile) -import Prelude hiding (readFile, writeFile) -import Data.Aeson hiding (json) -import Data.Text -import Data.Maybe (fromJust) - -data Comment = Comment { - commentText :: Text, - author :: Text - } deriving (Eq, Show, Ord) - -instance FromJSON Comment where - parseJSON (Object v) = Comment <$> - v .: "text" <*> - v .: "author" - parseJSON _ = mzero - -instance ToJSON Comment where - toJSON (Comment ctext author) = object ["text" .= ctext, "author" .= author] - - -main :: IO () -main = scotty 3000 $ do - - middleware $ staticPolicy (noDots >-> addBase "public") - middleware logStdoutDev - - get "/" $ file "./public/index.html" - - get "/api/comments" $ do - comments <- liftIO $ readFile "comments.json" - json $ fromJust $ (decode comments :: Maybe [Comment]) - - post "/api/comments" $ do - comments <- liftIO $ BS.readFile "comments.json" - let jsonComments = fromJust $ (decode $ fromStrict comments :: Maybe [Comment]) - author <- param "author" - comment <- param "text" - let allComments = jsonComments ++ [Comment comment author] - liftIO $ writeFile "comments.json" (encode allComments) - json allComments diff --git a/react-scotty.cabal b/react-scotty.cabal deleted file mode 100644 index a3024211..00000000 --- a/react-scotty.cabal +++ /dev/null @@ -1,28 +0,0 @@ --- Initial react-scotty.cabal generated by cabal init. For further --- documentation, see http://haskell.org/cabal/users-guide/ - -name: react-scotty -version: 0.1.0.0 -synopsis: React Haskell code with Scotty --- description: -license: GPL-2 -license-file: LICENSE -author: Sibi -maintainer: sibi@psibi.in --- copyright: -category: Web -build-type: Simple --- extra-source-files: -cabal-version: >=1.10 - -executable react-scotty - main-is: Server.hs - -- other-modules: - -- other-extensions: - build-depends: base >=4.8 && <4.9, - scotty, wai-extra, - mtl, text, aeson, - bytestring, - wai-middleware-static - -- hs-source-dirs: - default-language: Haskell2010 From 84129a5ed0dbd6e5b2f851d4bf41f4127cf894c8 Mon Sep 17 00:00:00 2001 From: Varun Maudgalya Date: Tue, 10 Nov 2015 16:50:17 -0800 Subject: [PATCH 08/33] revised error handling --- server.js | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index 2946e370..2a1ae582 100644 --- a/server.js +++ b/server.js @@ -26,7 +26,10 @@ app.use(bodyParser.urlencoded({extended: true})); app.get('/api/comments', function(req, res) { fs.readFile(COMMENTS_FILE, function(err, data) { - if (err) console.log(err); + if (err) { + console.error(err); + process.exit(1); + } res.setHeader('Cache-Control', 'no-cache'); res.json(JSON.parse(data)); }); @@ -34,11 +37,17 @@ app.get('/api/comments', function(req, res) { app.post('/api/comments', function(req, res) { fs.readFile(COMMENTS_FILE, function(err, data) { - if (err) console.log(err); + if (err) { + console.error(err); + process.exit(1); + } var comments = JSON.parse(data); comments.push(req.body); fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) { - if (err) console.log(err); + if (err) { + console.error(err); + process.exit(1); + } res.setHeader('Cache-Control', 'no-cache'); res.json(comments); }); From 0e7f1b2f7d58a059a67da9604c84ab055fdf3b53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Mon, 2 Nov 2015 17:20:56 -0800 Subject: [PATCH 09/33] Add ids to data server-side so that keys can be used client-side --- comments.json | 2 ++ public/scripts/example.js | 11 ++++++----- server.go | 4 +++- server.js | 10 +++++++++- server.php | 7 +++++-- server.pl | 2 ++ server.py | 5 ++++- server.rb | 2 +- 8 files changed, 32 insertions(+), 11 deletions(-) diff --git a/comments.json b/comments.json index 61f5ef60..7bef77ad 100644 --- a/comments.json +++ b/comments.json @@ -1,9 +1,11 @@ [ { + "id": 1388534400000, "author": "Pete Hunt", "text": "Hey there!" }, { + "id": 1420070400000, "author": "Paul O’Shannessy", "text": "React is *great*!" } diff --git a/public/scripts/example.js b/public/scripts/example.js index 2e0ee2a8..a3e5bc20 100644 --- a/public/scripts/example.js +++ b/public/scripts/example.js @@ -44,6 +44,10 @@ var CommentBox = React.createClass({ }, handleCommentSubmit: function(comment) { var comments = this.state.data; + // Optimistically set an id on the new comment. It will be replaced by an + // id generated by the server. In a production application you would likely + // not use Date.now() for this and would have a more robust system in place. + comment.id = Date.now(); var newComments = comments.concat([comment]); this.setState({data: newComments}); $.ajax({ @@ -80,12 +84,9 @@ var CommentBox = React.createClass({ var CommentList = React.createClass({ render: function() { - var commentNodes = this.props.data.map(function(comment, index) { + var commentNodes = this.props.data.map(function(comment) { return ( - // `key` is a React-specific concept and is not mandatory for the - // purpose of this tutorial. if you're curious, see more here: - // http://facebook.github.io/react/docs/multiple-components.html#dynamic-children - + {comment.text} ); diff --git a/server.go b/server.go index 9eb5d7d2..2224328d 100644 --- a/server.go +++ b/server.go @@ -22,9 +22,11 @@ import ( "net/http" "os" "sync" + "time" ) type comment struct { + ID int64 `json:"id"` Author string `json:"author"` Text string `json:"text"` } @@ -64,7 +66,7 @@ func handleComments(w http.ResponseWriter, r *http.Request) { } // Add a new comment to the in memory slice of comments - comments = append(comments, comment{Author: r.FormValue("author"), Text: r.FormValue("text")}) + comments = append(comments, comment{ID: time.Now().UnixNano() / 1000000, Author: r.FormValue("author"), Text: r.FormValue("text")}) // Marshal the comments to indented json. commentData, err = json.MarshalIndent(comments, "", " ") diff --git a/server.js b/server.js index 2a1ae582..ac87898a 100644 --- a/server.js +++ b/server.js @@ -42,7 +42,15 @@ app.post('/api/comments', function(req, res) { process.exit(1); } var comments = JSON.parse(data); - comments.push(req.body); + // NOTE: In a real implementation, we would likely rely on a database or + // some other approach (e.g. UUIDs) to ensure a globally unique id. We'll + // treat Date.now() as unique-enough for our purposes. + var newComment = { + id: Date.now(), + author: req.body.author, + text: req.body.text, + }; + comments.push(newComment); fs.writeFile(COMMENTS_FILE, JSON.stringify(comments, null, 4), function(err) { if (err) { console.error(err); diff --git a/server.php b/server.php index 53c19104..6b8880c8 100644 --- a/server.php +++ b/server.php @@ -34,8 +34,11 @@ function routeRequest() } elseif (preg_match('/\/api\/comments(\?.*)?/', $uri)) { if($_SERVER['REQUEST_METHOD'] === 'POST') { $commentsDecoded = json_decode($comments, true); - $commentsDecoded[] = ['author' => $_POST['author'], - 'text' => $_POST['text']]; + $commentsDecoded[] = [ + 'id' => round(microtime(true) * 1000), + 'author' => $_POST['author'], + 'text' => $_POST['text'] + ]; $comments = json_encode($commentsDecoded, JSON_PRETTY_PRINT); file_put_contents('comments.json', $comments); diff --git a/server.pl b/server.pl index ce1783e7..517e1621 100644 --- a/server.pl +++ b/server.pl @@ -8,6 +8,7 @@ # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +use Time::HiRes qw(gettimeofday); use Mojolicious::Lite; use Mojo::JSON qw(encode_json decode_json); @@ -22,6 +23,7 @@ if ($self->req->method eq 'POST') { push @$comments, { + id => int(gettimeofday * 1000), author => $self->param('author'), text => $self->param('text'), }; diff --git a/server.py b/server.py index 7b4920b9..451fbacd 100644 --- a/server.py +++ b/server.py @@ -10,6 +10,7 @@ import json import os +import time from flask import Flask, Response, request app = Flask(__name__, static_url_path='', static_folder='public') @@ -22,7 +23,9 @@ def comments_handler(): comments = json.loads(file.read()) if request.method == 'POST': - comments.append(request.form.to_dict()) + newComment = request.form.to_dict() + newComment['id'] = int(time.time() * 1000) + comments.append(newComment) with open('comments.json', 'w') as file: file.write(json.dumps(comments, indent=4, separators=(',', ': '))) diff --git a/server.rb b/server.rb index 4e9916b3..eed401ae 100644 --- a/server.rb +++ b/server.rb @@ -23,7 +23,7 @@ if req.request_method == 'POST' # Assume it's well formed - comment = {} + comment = { id: (Time.now.to_f * 1000).to_i } req.query.each do |key, value| comment[key] = value.force_encoding('UTF-8') end From 91abec61ef61de2b7a6229ba65fb7b9804cf72db Mon Sep 17 00:00:00 2001 From: Tay Yang Shun Date: Wed, 18 Nov 2015 14:55:06 +0800 Subject: [PATCH 10/33] Use controlled components for form inputs --- public/scripts/example.js | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/public/scripts/example.js b/public/scripts/example.js index a3e5bc20..c249427a 100644 --- a/public/scripts/example.js +++ b/public/scripts/example.js @@ -100,22 +100,40 @@ var CommentList = React.createClass({ }); var CommentForm = React.createClass({ + getInitialState: function() { + return {author: '', text: ''}; + }, + handleAuthorChange: function(e) { + this.setState({author: e.target.value}); + }, + handleTextChange: function(e) { + this.setState({text: e.target.value}); + }, handleSubmit: function(e) { e.preventDefault(); - var author = this.refs.author.value.trim(); - var text = this.refs.text.value.trim(); + var author = this.state.author.trim(); + var text = this.state.text.trim(); if (!text || !author) { return; } this.props.onCommentSubmit({author: author, text: text}); - this.refs.author.value = ''; - this.refs.text.value = ''; + this.setState({author: '', text: ''}); }, render: function() { return (
- - + +
); From 0d7ca5b4553ab2649c8e8dbd97868fe86d49e4a9 Mon Sep 17 00:00:00 2001 From: Mantas Kaveckas Date: Wed, 6 Jan 2016 17:08:04 +0200 Subject: [PATCH 11/33] Remove unessessary px suffix from size of zero pixels --- public/css/base.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/css/base.css b/public/css/base.css index bf382be3..08de8f1b 100644 --- a/public/css/base.css +++ b/public/css/base.css @@ -23,7 +23,7 @@ code { font-family: "Bitstream Vera Sans Mono", Consolas, Courier, monospace; font-size: 12px; margin: 0 2px; - padding: 0px 5px; + padding: 0 5px; } h1, h2, h3, h4 { From 46a9a9a8bb2573f1960305825ff8e924aa17d338 Mon Sep 17 00:00:00 2001 From: Anthony Ross Date: Sat, 23 Jan 2016 20:05:05 -0500 Subject: [PATCH 12/33] nil is false in ruby nil is false in ruby so the ternary operator can be used with more idiomatic ruby. Also added a comment to show how to execute with a custom port. --- server.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server.rb b/server.rb index eed401ae..d7f1121e 100644 --- a/server.rb +++ b/server.rb @@ -11,7 +11,9 @@ require 'webrick' require 'json' -port = ENV['PORT'].nil? ? 3000 : ENV['PORT'].to_i +# default port to 3000 or overwrite with PORT variable by running +# $ PORT=3001 ruby server.rb +port = ENV['PORT'] ? ENV['PORT'].to_i : 3000 puts "Server started: http://localhost:#{port}/" From e50157d498bb3a9d80ae334594753b55abe78554 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Sat, 23 Jan 2016 22:21:02 -0800 Subject: [PATCH 13/33] Ensure Ruby server doesn't have duplicate id fields in json Alternative approach to #115 --- server.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.rb b/server.rb index eed401ae..d902b4f6 100644 --- a/server.rb +++ b/server.rb @@ -25,7 +25,7 @@ # Assume it's well formed comment = { id: (Time.now.to_f * 1000).to_i } req.query.each do |key, value| - comment[key] = value.force_encoding('UTF-8') + comment[key] = value.force_encoding('UTF-8') unless key == 'id' end comments << comment File.write( From 3fba2d4e1ee9b5ab5253a0c1cdcdcc9bd7879f7b Mon Sep 17 00:00:00 2001 From: maxbittker Date: Sun, 24 Jan 2016 14:57:56 -0500 Subject: [PATCH 14/33] added permissive CORS header middleware function --- server.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/server.js b/server.js index ac87898a..c31d1e64 100644 --- a/server.js +++ b/server.js @@ -23,6 +23,11 @@ app.set('port', (process.env.PORT || 3000)); app.use('/', express.static(path.join(__dirname, 'public'))); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); +app.use(function(req, res, next) { + //set permissive CORS header + res.setHeader('Access-Control-Allow-Origin', '*'); + next(); +}); app.get('/api/comments', function(req, res) { fs.readFile(COMMENTS_FILE, function(err, data) { From d90d36b0c235d05d878837eca43f37a2421c32cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Mon, 25 Jan 2016 16:20:03 -0800 Subject: [PATCH 15/33] Clean up some code in the JS server, add comments --- server.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/server.js b/server.js index c31d1e64..b5a7218a 100644 --- a/server.js +++ b/server.js @@ -23,9 +23,15 @@ app.set('port', (process.env.PORT || 3000)); app.use('/', express.static(path.join(__dirname, 'public'))); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({extended: true})); + +// Additional middleware which will set headers that we need on each request. app.use(function(req, res, next) { - //set permissive CORS header + // Set permissive CORS header - this allows this server to be used only as + // an API server in conjunction with something like webpack-dev-server. res.setHeader('Access-Control-Allow-Origin', '*'); + + // Disable caching so we'll always get the latest comments. + res.setHeader('Cache-Control', 'no-cache'); next(); }); @@ -35,7 +41,6 @@ app.get('/api/comments', function(req, res) { console.error(err); process.exit(1); } - res.setHeader('Cache-Control', 'no-cache'); res.json(JSON.parse(data)); }); }); @@ -61,7 +66,6 @@ app.post('/api/comments', function(req, res) { console.error(err); process.exit(1); } - res.setHeader('Cache-Control', 'no-cache'); res.json(comments); }); }); From 304a251432b255635eeedccee23897c0d3684395 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Mon, 25 Jan 2016 16:42:19 -0800 Subject: [PATCH 16/33] Add cache control headers to perl server --- server.pl | 1 + 1 file changed, 1 insertion(+) diff --git a/server.pl b/server.pl index 517e1621..73c2713d 100644 --- a/server.pl +++ b/server.pl @@ -19,6 +19,7 @@ any [qw(GET POST)] => '/api/comments' => sub { my $self = shift; my $comments = decode_json (do { local(@ARGV,$/) = 'comments.json';<> }); + $self->res->headers->cache_control('no-cache'); if ($self->req->method eq 'POST') { From 7b675c89180cc50ce00fcf8f4bac39054102ec40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Mon, 25 Jan 2016 16:35:03 -0800 Subject: [PATCH 17/33] Add CORS headers to servers --- server.go | 2 ++ server.php | 1 + server.pl | 1 + server.py | 2 +- server.rb | 1 + 5 files changed, 6 insertions(+), 1 deletion(-) diff --git a/server.go b/server.go index 2224328d..934a4cfc 100644 --- a/server.go +++ b/server.go @@ -84,11 +84,13 @@ func handleComments(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Access-Control-Allow-Origin", "*") io.Copy(w, bytes.NewReader(commentData)) case "GET": w.Header().Set("Content-Type", "application/json") w.Header().Set("Cache-Control", "no-cache") + w.Header().Set("Access-Control-Allow-Origin", "*") // stream the contents of the file to the response io.Copy(w, bytes.NewReader(commentData)) diff --git a/server.php b/server.php index 6b8880c8..75fae215 100644 --- a/server.php +++ b/server.php @@ -45,6 +45,7 @@ function routeRequest() } header('Content-Type: application/json'); header('Cache-Control: no-cache'); + header('Access-Control-Allow-Origin: *'); echo $comments; } else { return false; diff --git a/server.pl b/server.pl index 73c2713d..c3212b9c 100644 --- a/server.pl +++ b/server.pl @@ -20,6 +20,7 @@ my $self = shift; my $comments = decode_json (do { local(@ARGV,$/) = 'comments.json';<> }); $self->res->headers->cache_control('no-cache'); + $self->res->headers->access_control_allow_origin('*'); if ($self->req->method eq 'POST') { diff --git a/server.py b/server.py index 451fbacd..5cf598df 100644 --- a/server.py +++ b/server.py @@ -30,7 +30,7 @@ def comments_handler(): with open('comments.json', 'w') as file: file.write(json.dumps(comments, indent=4, separators=(',', ': '))) - return Response(json.dumps(comments), mimetype='application/json', headers={'Cache-Control': 'no-cache'}) + return Response(json.dumps(comments), mimetype='application/json', headers={'Cache-Control': 'no-cache', 'Access-Control-Allow-Origin': '*'}) if __name__ == '__main__': app.run(port=int(os.environ.get("PORT",3000))) diff --git a/server.rb b/server.rb index fc81b701..698f4339 100644 --- a/server.rb +++ b/server.rb @@ -40,6 +40,7 @@ # always return json res['Content-Type'] = 'application/json' res['Cache-Control'] = 'no-cache' + res['Access-Control-Allow-Origin'] = '*' res.body = JSON.generate(comments) end From 19aadd8a295acbfefbfd1f562073b0685bf60528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 16 Feb 2016 13:20:50 -0800 Subject: [PATCH 18/33] Update CDN links to latest versions --- public/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/index.html b/public/index.html index c6494446..21340e72 100644 --- a/public/index.html +++ b/public/index.html @@ -5,11 +5,11 @@ React Tutorial - - + + - - + +
From 31fe8d2ad766853ac5427c2fef08f2cfd37dcc33 Mon Sep 17 00:00:00 2001 From: Fokko Driesprong Date: Thu, 31 Mar 2016 20:23:09 +0200 Subject: [PATCH 19/33] Update CDN links to latest versions --- public/index.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/index.html b/public/index.html index 21340e72..4a560b84 100644 --- a/public/index.html +++ b/public/index.html @@ -5,10 +5,10 @@ React Tutorial - - - - + + + + From cd5dbc7a3c88aa60c04129310cac8f12af48c9e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Thu, 7 Apr 2016 15:41:18 -0700 Subject: [PATCH 20/33] Use v15 --- public/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 4a560b84..8b84e266 100644 --- a/public/index.html +++ b/public/index.html @@ -5,8 +5,8 @@ React Tutorial - - + + From 2be1a2d6999b8f47c34e52e5a5b05bd6713343fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Fri, 8 Apr 2016 13:53:45 -0700 Subject: [PATCH 21/33] Use 15.0.1 --- public/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 8b84e266..34ebddf4 100644 --- a/public/index.html +++ b/public/index.html @@ -5,8 +5,8 @@ React Tutorial - - + + From 82424fa6ce90f384e418c54bd9bdc61216e550d8 Mon Sep 17 00:00:00 2001 From: Andrew Abraham Date: Tue, 10 May 2016 15:53:38 -0700 Subject: [PATCH 22/33] Remove shadowing of file builtin in server.py. PEP8 formatting --- server.py | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/server.py b/server.py index 5cf598df..fad15a66 100644 --- a/server.py +++ b/server.py @@ -16,21 +16,29 @@ app = Flask(__name__, static_url_path='', static_folder='public') app.add_url_rule('/', 'root', lambda: app.send_static_file('index.html')) + @app.route('/api/comments', methods=['GET', 'POST']) def comments_handler(): - - with open('comments.json', 'r') as file: - comments = json.loads(file.read()) + with open('comments.json', 'r') as f: + comments = json.loads(f.read()) if request.method == 'POST': - newComment = request.form.to_dict() - newComment['id'] = int(time.time() * 1000) - comments.append(newComment) + new_comment = request.form.to_dict() + new_comment['id'] = int(time.time() * 1000) + comments.append(new_comment) + + with open('comments.json', 'w') as f: + f.write(json.dumps(comments, indent=4, separators=(',', ': '))) - with open('comments.json', 'w') as file: - file.write(json.dumps(comments, indent=4, separators=(',', ': '))) + return Response( + json.dumps(comments), + mimetype='application/json', + headers={ + 'Cache-Control': 'no-cache', + 'Access-Control-Allow-Origin': '*' + } + ) - return Response(json.dumps(comments), mimetype='application/json', headers={'Cache-Control': 'no-cache', 'Access-Control-Allow-Origin': '*'}) if __name__ == '__main__': - app.run(port=int(os.environ.get("PORT",3000))) + app.run(port=int(os.environ.get("PORT", 3000))) From 4fa16fde3795ff7047322f28320cffc3b2b385ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Fri, 20 May 2016 10:28:43 -0700 Subject: [PATCH 23/33] Add private & license fields to package.json --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index e7491981..bf3360a0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,8 @@ { "name": "react-tutorial", "version": "0.0.0", + "private": true, + "license": "see LICENSE file", "description": "Code from the React tutorial.", "main": "server.js", "dependencies": { From 06b89a1b5d1abe74f58163efeed80959c993ee52 Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Fri, 3 Jun 2016 14:35:54 -0700 Subject: [PATCH 24/33] Use remarkable instead of marked (#140) Closes #139. --- public/index.html | 2 +- public/scripts/example.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 34ebddf4..a76aaada 100644 --- a/public/index.html +++ b/public/index.html @@ -9,7 +9,7 @@ - +
diff --git a/public/scripts/example.js b/public/scripts/example.js index c249427a..6493fea9 100644 --- a/public/scripts/example.js +++ b/public/scripts/example.js @@ -12,7 +12,8 @@ var Comment = React.createClass({ rawMarkup: function() { - var rawMarkup = marked(this.props.children.toString(), {sanitize: true}); + var md = new Remarkable(); + var rawMarkup = md.render(this.props.children.toString()); return { __html: rawMarkup }; }, From 64a6dfca72aca4d13ab4cbf23c50eba8b9fabe8a Mon Sep 17 00:00:00 2001 From: saiyam-gambhir Date: Wed, 8 Jun 2016 23:09:19 +0530 Subject: [PATCH 25/33] Removed duplicate CSS (#143) --- public/css/base.css | 3 --- 1 file changed, 3 deletions(-) diff --git a/public/css/base.css b/public/css/base.css index 08de8f1b..c8cc35f7 100644 --- a/public/css/base.css +++ b/public/css/base.css @@ -35,9 +35,6 @@ h1, h2, h3, h4 { h1 { border-bottom: 1px solid #ddd; font-size: 2.5em; - font-weight: bold; - margin: 0 0 15px; - padding: 0; } h2 { From e5786f844bff18dfa3ff6330b67c9f856c5ebbf6 Mon Sep 17 00:00:00 2001 From: sthodup1 Date: Mon, 20 Jun 2016 15:13:45 -0500 Subject: [PATCH 26/33] Update React Dependency to 15.1.0 --- public/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index a76aaada..ec158df2 100644 --- a/public/index.html +++ b/public/index.html @@ -5,8 +5,8 @@ React Tutorial - - + + From 2f565db733f7614d19012f029a52f65d294b7db0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Fri, 1 Jul 2016 12:29:47 -0700 Subject: [PATCH 27/33] Update for 15.2.0 --- public/index.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index ec158df2..1ce8900c 100644 --- a/public/index.html +++ b/public/index.html @@ -5,8 +5,8 @@ React Tutorial - - + + From 08115a6ec2df124bb03cc04974f2c5b9b290804e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Tue, 2 Aug 2016 13:50:54 -0700 Subject: [PATCH 28/33] Use npmcdn (#152) --- public/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/index.html b/public/index.html index 1ce8900c..5af72a45 100644 --- a/public/index.html +++ b/public/index.html @@ -5,11 +5,11 @@ React Tutorial - - - - - + + + + +
From ddc30f08e010ca1401c7c9ef8f753c0749dbc499 Mon Sep 17 00:00:00 2001 From: Jonathan Herbert Date: Sat, 20 Aug 2016 20:00:30 -0400 Subject: [PATCH 29/33] Only Read Comments File On Comments Route (#154) --- server.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.php b/server.php index 75fae215..e510136b 100644 --- a/server.php +++ b/server.php @@ -27,11 +27,11 @@ function routeRequest() { - $comments = file_get_contents('comments.json'); $uri = $_SERVER['REQUEST_URI']; if ($uri == '/') { echo file_get_contents('./public/index.html'); } elseif (preg_match('/\/api\/comments(\?.*)?/', $uri)) { + $comments = file_get_contents('comments.json'); if($_SERVER['REQUEST_METHOD'] === 'POST') { $commentsDecoded = json_decode($comments, true); $commentsDecoded[] = [ From 7d0728e6d9011658420b7b30463edb2163577a15 Mon Sep 17 00:00:00 2001 From: Mike Sukmanowsky Date: Mon, 29 Aug 2016 20:08:11 -0400 Subject: [PATCH 30/33] Set debug=True flag for Flask server (#156) --- server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server.py b/server.py index fad15a66..03c6213d 100644 --- a/server.py +++ b/server.py @@ -41,4 +41,4 @@ def comments_handler(): if __name__ == '__main__': - app.run(port=int(os.environ.get("PORT", 3000))) + app.run(port=int(os.environ.get("PORT", 3000)), debug=True) From 35b5c0c77c0c5e4b159f78a85a66110086aaddfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Dani=C4=87?= Date: Tue, 30 Aug 2016 19:31:59 +0200 Subject: [PATCH 31/33] Use unpkg instead of npmcdn (#157) npmcdn.com is moving to unpkg.com and these links will eventually switch to 301. Better to switch to unpkg right away. https://twitter.com/mjackson/status/770424625754939394 --- public/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/index.html b/public/index.html index 5af72a45..ca5fb5fc 100644 --- a/public/index.html +++ b/public/index.html @@ -5,11 +5,11 @@ React Tutorial - - - - - + + + + +
From 70f7e15f3d4b048625a712713a494f7860695255 Mon Sep 17 00:00:00 2001 From: Jisu Park Date: Wed, 7 Sep 2016 02:25:07 +0900 Subject: [PATCH 32/33] feat(babel): Bump up the babel version 5.x to 6.x (#158) --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index ca5fb5fc..b88096b6 100644 --- a/public/index.html +++ b/public/index.html @@ -7,7 +7,7 @@ - + From ec8d845a8a361abf86c11af2d693150697ef858a Mon Sep 17 00:00:00 2001 From: Ben Alpert Date: Mon, 3 Oct 2016 11:06:17 -0700 Subject: [PATCH 33/33] remarkable 1.7.1 --- comments.json | 17 ++++++++++++++++- public/index.html | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/comments.json b/comments.json index 7bef77ad..28816136 100644 --- a/comments.json +++ b/comments.json @@ -8,5 +8,20 @@ "id": 1420070400000, "author": "Paul O’Shannessy", "text": "React is *great*!" + }, + { + "id": 1464988635157, + "author": "ben", + "text": "*abc*" + }, + { + "id": 1464988636500, + "author": "ben", + "text": "*abc*" + }, + { + "id": 1464988717637, + "author": "evil", + "text": "alert(1)" } -] +] \ No newline at end of file diff --git a/public/index.html b/public/index.html index b88096b6..eb201204 100644 --- a/public/index.html +++ b/public/index.html @@ -9,7 +9,7 @@ - +