+ Showing {this.props.start} - {this.props.end} of {this.props.count}
+
+ )
+ }
+});
+
+ReactDOM.render(
+ ,
+ document.getElementById('content')
+);
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 632a1efa..00000000
--- a/requirements.txt
+++ /dev/null
@@ -1 +0,0 @@
-Flask==0.10.1
diff --git a/server.go b/server.go
index 934a4cfc..00ab9a49 100644
--- a/server.go
+++ b/server.go
@@ -8,6 +8,8 @@
* 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.
+
+ * edited by: Emily Feder
*/
package main
@@ -23,18 +25,38 @@ import (
"os"
"sync"
"time"
+ "strconv"
)
-type comment struct {
+type Comment struct {
ID int64 `json:"id"`
Author string `json:"author"`
Text string `json:"text"`
}
+type Response struct {
+ Comments []Comment `json:"comments"`
+ Count int `json:"count"`
+}
+
const dataFile = "./comments.json"
var commentMutex = new(sync.Mutex)
+func writeCommentsToFile(comments []Comment, fi os.FileInfo) (string) {
+ var commentData, err = json.MarshalIndent(comments, "", " ")
+ if err != nil {
+ return fmt.Sprintf("Unable to marshal comments to data file (%s): %s", dataFile, err)
+ }
+ // Write out the comments to the file, preserving permissions
+ err = ioutil.WriteFile(dataFile, commentData, fi.Mode())
+ if err != nil {
+ return fmt.Sprintf("Unable to write comments to data file (%s): %s", dataFile, err)
+ }
+
+ return ""
+}
+
// Handle comments
func handleComments(w http.ResponseWriter, r *http.Request) {
// Since multiple requests could come in at once, ensure we have a lock
@@ -56,43 +78,81 @@ func handleComments(w http.ResponseWriter, r *http.Request) {
return
}
+ // Decode the JSON data
+ var comments []Comment
+ if err := json.Unmarshal(commentData, &comments); err != nil {
+ http.Error(w, fmt.Sprintf("Unable to Unmarshal comments from data file (%s): %s", dataFile, err), http.StatusInternalServerError)
+ return
+ }
+
+ var start, _ = strconv.ParseInt(r.URL.Query().Get("start"), 10, 64);
+ var end, _ = strconv.ParseInt(r.URL.Query().Get("end"), 10, 64);
+
switch r.Method {
case "POST":
- // Decode the JSON data
- var comments []comment
- if err := json.Unmarshal(commentData, &comments); err != nil {
- http.Error(w, fmt.Sprintf("Unable to Unmarshal comments from data file (%s): %s", dataFile, err), http.StatusInternalServerError)
- return
+ //delete or add a comment
+ if r.FormValue("reason") == "delete" {
+ var newcomments []Comment
+ for _, c := range comments {
+ var id, err = strconv.ParseInt(r.FormValue("id"), 10, 64);
+ if err == nil && c.ID != id {
+ newcomments = append(newcomments, c);
+ }
+ }
+ comments = newcomments
+ } else {
+ comments = append([]Comment{{ID: time.Now().UnixNano() / 1000000, Author: r.FormValue("author"), Text: r.FormValue("text")}}, comments...)
+ }
+
+ //refresh the end
+ if (len(comments) == 0) {
+ end = 0
+ } else if (end > int64(len(comments))) {
+ end = int64(len(comments))
}
- // Add a new comment to the in memory slice of comments
- comments = append(comments, comment{ID: time.Now().UnixNano() / 1000000, Author: r.FormValue("author"), Text: r.FormValue("text")})
+ response := Response{Comments:comments[start:end], Count: len(comments)}
- // Marshal the comments to indented json.
- commentData, err = json.MarshalIndent(comments, "", " ")
+ // Marshal the response to indented json.
+ responseData, err := json.MarshalIndent(response, "", " ")
if err != nil {
- http.Error(w, fmt.Sprintf("Unable to marshal comments to json: %s", err), http.StatusInternalServerError)
+ http.Error(w, fmt.Sprintf("Unable to marshal response to json: %s", err), http.StatusInternalServerError)
return
}
// Write out the comments to the file, preserving permissions
- err := ioutil.WriteFile(dataFile, commentData, fi.Mode())
- if err != nil {
- http.Error(w, fmt.Sprintf("Unable to write comments to data file (%s): %s", dataFile, err), http.StatusInternalServerError)
+ write_err := writeCommentsToFile(comments, fi)
+ if write_err != "" {
+ http.Error(w, write_err, http.StatusInternalServerError)
return
}
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))
+ io.Copy(w, bytes.NewReader(responseData))
case "GET":
w.Header().Set("Content-Type", "application/json")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Access-Control-Allow-Origin", "*")
+
+ if (len(comments) == 0) {
+ end = 0
+ } else if (end > int64(len(comments))) {
+ end = int64(len(comments))
+ }
+
+ response := Response{Comments:comments[start:end], Count: len(comments)}
+
// stream the contents of the file to the response
- io.Copy(w, bytes.NewReader(commentData))
+ responseData, err := json.MarshalIndent(response, "", " ")
+ if err != nil {
+ http.Error(w, fmt.Sprintf("Unable to marshal response to json: %s", err), http.StatusInternalServerError)
+ return
+ }
+
+ io.Copy(w, bytes.NewReader(responseData))
default:
// Don't know the method, so error
diff --git a/server.js b/server.js
deleted file mode 100644
index b5a7218a..00000000
--- a/server.js
+++ /dev/null
@@ -1,77 +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.
- */
-
-var fs = require('fs');
-var path = require('path');
-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')));
-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 - 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();
-});
-
-app.get('/api/comments', function(req, res) {
- fs.readFile(COMMENTS_FILE, function(err, data) {
- if (err) {
- console.error(err);
- process.exit(1);
- }
- res.json(JSON.parse(data));
- });
-});
-
-app.post('/api/comments', function(req, res) {
- fs.readFile(COMMENTS_FILE, function(err, data) {
- if (err) {
- console.error(err);
- process.exit(1);
- }
- var comments = JSON.parse(data);
- // 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);
- process.exit(1);
- }
- res.json(comments);
- });
- });
-});
-
-
-app.listen(app.get('port'), function() {
- console.log('Server started: http://localhost:' + app.get('port') + '/');
-});
diff --git a/server.php b/server.php
deleted file mode 100644
index 75fae215..00000000
--- a/server.php
+++ /dev/null
@@ -1,53 +0,0 @@
- round(microtime(true) * 1000),
- 'author' => $_POST['author'],
- 'text' => $_POST['text']
- ];
-
- $comments = json_encode($commentsDecoded, JSON_PRETTY_PRINT);
- file_put_contents('comments.json', $comments);
- }
- 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
deleted file mode 100644
index c3212b9c..00000000
--- a/server.pl
+++ /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.
-
-use Time::HiRes qw(gettimeofday);
-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';<> });
- $self->res->headers->cache_control('no-cache');
- $self->res->headers->access_control_allow_origin('*');
-
- if ($self->req->method eq 'POST')
- {
- push @$comments, {
- id => int(gettimeofday * 1000),
- 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");
diff --git a/server.py b/server.py
deleted file mode 100644
index 5cf598df..00000000
--- a/server.py
+++ /dev/null
@@ -1,36 +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.
-
-import json
-import os
-import time
-from flask import Flask, Response, request
-
-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())
-
- if request.method == 'POST':
- 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=(',', ': ')))
-
- 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
deleted file mode 100644
index 698f4339..00000000
--- a/server.rb
+++ /dev/null
@@ -1,49 +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.
-
-require 'webrick'
-require 'json'
-
-# 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}/"
-
-root = File.expand_path './public'
-server = WEBrick::HTTPServer.new Port: port, DocumentRoot: root
-
-server.mount_proc '/api/comments' do |req, res|
- comments = JSON.parse(File.read('./comments.json', encoding: 'UTF-8'))
-
- if req.request_method == 'POST'
- # 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') unless key == 'id'
- end
- comments << comment
- File.write(
- './comments.json',
- JSON.pretty_generate(comments, indent: ' '),
- encoding: 'UTF-8'
- )
- end
-
- # always return json
- res['Content-Type'] = 'application/json'
- res['Cache-Control'] = 'no-cache'
- res['Access-Control-Allow-Origin'] = '*'
- res.body = JSON.generate(comments)
-end
-
-trap('INT') { server.shutdown }
-
-server.start