From 3b6dd7032ae32b9f606016bc378326e46ad2489e Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Wed, 14 Dec 2016 22:22:34 -0800 Subject: [PATCH 01/14] first commit, npm init --- package.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..34e0e5a --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "07-vanilla-http-server", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/maschigokae/07-vanilla-http-server.git" + }, + "keywords": [], + "author": "", + "license": "ISC", + "bugs": { + "url": "https://github.com/maschigokae/07-vanilla-http-server/issues" + }, + "homepage": "https://github.com/maschigokae/07-vanilla-http-server#readme" +} From 46ccaac1f28957e793a815e38d0150d53efdbd02 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:26:47 -0800 Subject: [PATCH 02/14] add gulpfile --- gulpfile.js | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 gulpfile.js diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..04eaa14 --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,23 @@ +'use strict'; + +const gulp = require('gulp'); +const eslint = require('gulp-eslint'); +const mocha = require('gulp-mocha'); + +gulp.task('test', function() { + gulp.src('./test/*-test.js', { read: false }) + .pipe(mocha({ reporter: 'spec' })); +}); + +gulp.task('lint', function() { + gulp.src(['**/*.js', '!node_modules']) + .pipe(eslint()) + .pipe(eslint.format()) + .pipe(eslint.failAfterError()); +}); + +gulp.task('dev', function() { + gulp.watch(['**/*.js', '!node_modules'], ['lint', 'test']); +}); + +gulp.task('default', ['dev']); From f130d7f1fe2cdae7ab2434b5c138a00c310eda89 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:27:13 -0800 Subject: [PATCH 03/14] set up .eslintrc file --- .eslintrc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .eslintrc diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..8dc6807 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,21 @@ +{ + "rules": { + "no-console": "off", + "indent": [ "error", 2 ], + "quotes": [ "error", "single" ], + "semi": ["error", "always"], + "linebreak-style": [ "error", "unix" ] + }, + "env": { + "es6": true, + "node": true, + "mocha": true, + "jasmine": true + }, + "ecmaFeatures": { + "modules": true, + "experimentalObjectRestSpread": true, + "impliedStrict": true + }, + "extends": "eslint:recommended" +} From 34cc6dbfca2ba873e722f410337446f8c03bc788 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:27:30 -0800 Subject: [PATCH 04/14] set up .gitignore file --- .gitignore | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..88ea613 --- /dev/null +++ b/.gitignore @@ -0,0 +1,105 @@ +# Created by https://www.gitignore.io/api/macos,node,vim,linux + +### macOS ### +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon +# Thumbnails +._* +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + + +### Node ### +node_modules +# Logs +logs +*.log +npm-debug.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (http://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules +jspm_packages + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + + + +### Vim ### +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + + +### Linux ### + +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* From fea2c44ae39c4ee3dce6651019df3ed4251100e4 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:32:09 -0800 Subject: [PATCH 05/14] add cowsay to dependencies --- package.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 34e0e5a..957d1b8 100644 --- a/package.json +++ b/package.json @@ -16,5 +16,8 @@ "bugs": { "url": "https://github.com/maschigokae/07-vanilla-http-server/issues" }, - "homepage": "https://github.com/maschigokae/07-vanilla-http-server#readme" + "homepage": "https://github.com/maschigokae/07-vanilla-http-server#readme", + "dependencies": { + "cowsay": "^1.1.9" + } } From 9c4894a8e2752866ece71c1e62e7d88a1ea5bd9f Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:33:26 -0800 Subject: [PATCH 06/14] set up README.md file --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5ddb78 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +**Documentation Coming Soon** From 1a22d91b7fa21941b51ec147a8f9d81dbd676a07 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:35:15 -0800 Subject: [PATCH 07/14] set up server.js file --- server.js | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 server.js diff --git a/server.js b/server.js new file mode 100644 index 0000000..ee752d3 --- /dev/null +++ b/server.js @@ -0,0 +1,5 @@ +'use strict'; + +const http = require('http'); + +// BUILD OUT REST OF SERVER From 6413d1450ce419e822f1673a7a53282424f952b5 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 01:37:31 -0800 Subject: [PATCH 08/14] set up lib directory, parse-body.js file --- lib/parse-body.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 lib/parse-body.js diff --git a/lib/parse-body.js b/lib/parse-body.js new file mode 100644 index 0000000..86eff22 --- /dev/null +++ b/lib/parse-body.js @@ -0,0 +1,3 @@ +'use strict'; + +// TODO: BUILD OUT PARSE BODY MODULE From dbe0af5e7befc812d8d3d0adb1351a78b49218ad Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 15:32:15 -0800 Subject: [PATCH 09/14] set up basic app dependencies, set up simple http server --- server.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/server.js b/server.js index ee752d3..8661767 100644 --- a/server.js +++ b/server.js @@ -1,5 +1,15 @@ 'use strict'; const http = require('http'); +const url = require('url'); +const querystring = require('querystring'); +const cowsay = require('cowsay'); +const PORT = process.env.PORT || 8000; -// BUILD OUT REST OF SERVER +const server = http.createServer(function(req, res) { + // TODO: BUILD OUT REST OF SERVER +}); + +server.listen(PORT, () => { + console.log(`SERVER RUNNING ON PORT ${PORT}.`); +}); From e963146e671870ea664701b0655000185a3d614a Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 15:37:45 -0800 Subject: [PATCH 10/14] build out GET request handling --- server.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/server.js b/server.js index 8661767..2dc9c79 100644 --- a/server.js +++ b/server.js @@ -8,6 +8,15 @@ const PORT = process.env.PORT || 8000; const server = http.createServer(function(req, res) { // TODO: BUILD OUT REST OF SERVER + + req.url = url.parse(req.url); + req.url.query = querystring.parse(req.url.query); + + if (req.method === 'GET' && req.url.pathname === '/cowsay') { + console.log('get request to cowsay'); + res.write(cowsay.say({text: 'hello from cowville'})); + res.end(); + } }); server.listen(PORT, () => { From cbf4c2f22dc5aefdf20b77f3915e052e3d60cde9 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 15:40:57 -0800 Subject: [PATCH 11/14] build out parse-body module --- lib/parse-body.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/parse-body.js b/lib/parse-body.js index 86eff22..d5b5766 100644 --- a/lib/parse-body.js +++ b/lib/parse-body.js @@ -1,3 +1,18 @@ 'use strict'; -// TODO: BUILD OUT PARSE BODY MODULE +module.exports = function(req, callback) { + req.body = ''; + + req.on('data', function(data) { + req.body += data.toString(); + }); + + req.on('end', function() { + try { + req.body = JSON.parse(req.body); + callback(null, req.body); + } catch (err) { + callback(err); + } + }); +}; From 2ca83b2a1c6fba64471322b84863c4cf0ded9c73 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 15:47:44 -0800 Subject: [PATCH 12/14] require parse-body module, build out POST request handling --- server.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/server.js b/server.js index 2dc9c79..c2bea9f 100644 --- a/server.js +++ b/server.js @@ -4,6 +4,7 @@ const http = require('http'); const url = require('url'); const querystring = require('querystring'); const cowsay = require('cowsay'); +const parseBody = require('./lib/parse-body.js'); const PORT = process.env.PORT || 8000; const server = http.createServer(function(req, res) { @@ -17,6 +18,12 @@ const server = http.createServer(function(req, res) { res.write(cowsay.say({text: 'hello from cowville'})); res.end(); } + + if (req.method === 'POST') { + parseBody(req, function(err) { + console.log(`POST request body: ${req.body}`); + }); + } }); server.listen(PORT, () => { From 62e661e79669296a8b32c108af30a4927a59e6d8 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 23:13:18 -0800 Subject: [PATCH 13/14] build out more request handlers --- server.js | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/server.js b/server.js index c2bea9f..d959c58 100644 --- a/server.js +++ b/server.js @@ -8,20 +8,73 @@ const parseBody = require('./lib/parse-body.js'); const PORT = process.env.PORT || 8000; const server = http.createServer(function(req, res) { - // TODO: BUILD OUT REST OF SERVER req.url = url.parse(req.url); req.url.query = querystring.parse(req.url.query); - if (req.method === 'GET' && req.url.pathname === '/cowsay') { + // REQUESTS TO ROOT URL + if (req.method === 'POST' && req.url.pathname === '/') { + console.log('successful request to home'); + res.writeHead(200, + { + 'Content-Type': 'text/plain', + } + ); + res.write('hello from my server!'); + res.end(); + } + + if (req.method === 'GET' && req.url.pathname === '/') { + console.log('successful request to home'); + res.writeHead(200, + { + 'Content-Type': 'text/plain', + } + ); + res.write('hello from my server!'); + res.end(); + } + + // REQUESTS TO COWSAY URL + if (req.method === 'GET' && req.url.pathname === '/cowsay' && !req.url.query.text) { + res.writeHead(200, + { + 'Content-Type': 'text/plain', + } + ); console.log('get request to cowsay'); res.write(cowsay.say({text: 'hello from cowville'})); res.end(); } - if (req.method === 'POST') { + if (req.method === 'GET' && req.url.pathname === '/cowsay' && req.url.query.text) { + res.writeHead(200, + { + 'Content-Type': 'text/plain', + } + ); + res.write(cowsay.say({text: req.url.query.text})); + res.end(); + } + + if (req.method === 'POST' && req.url.pathname === '/cowsay' && req.url.query.text) { + parseBody(req, function(err) { + console.log(`POST request body: ${req.url.query.text}`); + res.writeHead(200, + { + 'Content-Type': 'text/plain', + } + ); + res.write(cowsay.say({text: req.url.query.text})); + res.end(); + }); + } + + if (req.method === 'POST' && req.url.pathname === '/cowsay' && !req.url.query.text) { parseBody(req, function(err) { - console.log(`POST request body: ${req.body}`); + res.writeHead(400); + res.write(cowsay.say({text: 'BAD REQUEST.'})); + res.end(); }); } }); From cd9ec4f5c06070a20a0912ff1c8605eb83c63789 Mon Sep 17 00:00:00 2001 From: Caleb Sattgast Date: Fri, 24 Feb 2017 23:13:43 -0800 Subject: [PATCH 14/14] add basic documentation for app --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c5ddb78..dc9a0cd 100644 --- a/README.md +++ b/README.md @@ -1 +1,13 @@ -**Documentation Coming Soon** +**Documentation for Cowsay API, a demonstration of a basic Node HTTP server** + +Use query strings to have the cow repeat the text you enter. This documentation assumes you are using a Mac and have httpie installed. + +* To run this app, clone down the repo and run npm i to install the dependencies. In a terminal window in the root directory of the app, type `node server.js`. + +* In a separate terminal window (location for this window doesn't matter), and type `http :8000/` or `http POST :8000/`. You will get a welcome message printed in the terminal and an http response with 200-OK status code. + +* Let's make a request to the /cowsay route. type `http :8000/cowsay`. You should get a cow printed in your response with a speech balloon saying "Welcome to Cowville." + +* You can make the cow say anything you want by simply adding a query string to the end of the url, with 'text' as the key. For example, if you type `http :8000/cowsay?text=cows+say+mooooo` or `http POST :8000/cowsay?text=cows+say+mooooo`, your cow will say "cows say mooooo". The plus signs in the query string indicate spaces. + +* if you try to submit `http POST :8000/cowsay`, your cow will give you a bad request response, accompanied by a 400 error status code.