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" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a9b5dba --- /dev/null +++ b/.gitignore @@ -0,0 +1,93 @@ +# Created by https://www.gitignore.io/api/node,macos,vim,git + +### Node ### +# 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 + + + +### 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 + + +### Vim ### +# swap +[._]*.s[a-w][a-z] +[._]s[a-w][a-z] +# session +Session.vim +# temporary +.netrwhist +*~ +# auto-generated tag files +tags + + +### Git ### +*.orig diff --git a/README.md b/README.md new file mode 100644 index 0000000..b299331 --- /dev/null +++ b/README.md @@ -0,0 +1,31 @@ +### HTTP Cowsay Project + +This is a fun project where you can practice GET and POST requests using HTTPIE and the Cowsay npm package! Woo! + +A visualization of the HTTP Cowsay project may be seen below (credit to [Brian Nations](https://github.com/bnates)): + +![alt text](https://raw.githubusercontent.com/codefellows/seattle-javascript-401d12/master/07-http_and_rest_apis/demo/visualization/http-server.png) + +### Get the Project Running + +To get this project running, type the following in your command line: + +1. `git clone https://github.com/brittdawn/07-vanilla-http-server.git` +2. `cd 07-vanilla-http-server.git` +3. `npm i` +4. `brew install httpie` +4. `node server.js` + +You will now see the phrase "server is up: 3000" if you have not already specified a port number. + +### Test the Vanilla HTTP Server + +1. Open a new terminal located at the root of this project and type `http localhost:3000/` +2. You should get a response saying 'hello from my server' +3. Play with the GET and POST requests below. + +### Interacting with HTTP Endpoints + +To make an initial GET request, type this in the terminal: `http localhost:3000/cowsay?text=hi`. A cow will appear with a text of hi. If you have made a bad request, a sad Ren will appear. You can change the text to whatever you would like. + +To make a POST request, type this in the terminal: `http POST localhost:3000/cowsay text=hello`. You can change the text to whatever you would like. diff --git a/data.json b/data.json new file mode 100644 index 0000000..0702211 --- /dev/null +++ b/data.json @@ -0,0 +1,3 @@ +{ + "text": "hello" +} diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000..6db050d --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,37 @@ +'use strict'; + +const gulp = require('gulp'); +const eslint = require('gulp-eslint'); +const mocha = require('gulp-mocha'); +const cache = require('gulp-cache'); +const istanbul = require('gulp-istanbul'); + +gulp.task('pre-test', function() { + return gulp.src(['./lib/*.js', './model/*.js', '!node_modules/**']) + .pipe(istanbul()) + .pipe(istanbul.hookRequire()); +}); + +gulp.task('test', ['pre-test'], function() { + gulp.src('./test/*-test.js', { read: false}) + .pipe(mocha({ report: 'spec'})) + .pipe(istanbul.writeReports()) + .pipe(istanbul.enforceThresholds({thresholds: {global: 90}})); +}); + +gulp.task('lint', function() { + return 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']); + +gulp.task('clear', function (done) { + return cache.clearAll(done); +}); diff --git a/lib/parse-body.js b/lib/parse-body.js new file mode 100644 index 0000000..d5b5766 --- /dev/null +++ b/lib/parse-body.js @@ -0,0 +1,18 @@ +'use strict'; + +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); + } + }); +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..e1302da --- /dev/null +++ b/package.json @@ -0,0 +1,26 @@ +{ + "name": "http", + "version": "1.0.0", + "description": "Fun Cowsay HTTP Lab.", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "cowsay": "^1.1.9", + "querystring": "^0.2.0" + }, + "devDependencies": { + "chai": "^3.5.0", + "eslint": "^3.12.1", + "gulp": "^3.9.1", + "gulp-cache": "^0.4.5", + "gulp-eslint": "^3.0.1", + "gulp-istanbul": "^1.1.1", + "gulp-mocha": "^3.0.1", + "mocha": "^3.2.0" + } +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..66868c3 --- /dev/null +++ b/server.js @@ -0,0 +1,66 @@ +'use strict'; + +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 || 3000; + +const server = http.createServer(function(req, res) { + req.url = url.parse(req.url); + req.url.query = querystring.parse(req.url.query); + + if (req.url.pathname === '/'){ + res.writeHead(200, { + 'Content-Type': 'text/plain' + }); + res.write('hello from my server'); + return res.end(); + } + + if (req.method === 'GET' && req.url.pathname === '/cowsay') { + try { + res.writeHead(200, { + 'Content-Type': 'text/plain' + }); + res.write(cowsay.say(req.url.query)); + } catch (err) { + res.writeHead(400); + res.write(cowsay.think({ + text: 'Bad Request. Ren is sad. You could try: http localhost:3000/cowsay?text=hi', + f: 'ren' + })); + } + return res.end(); + } + + if(req.method === 'POST' && req.url.pathname === '/cowsay') { + parseBody(req, function(err) { + if (err) return console.error(err); + if(req.body.text) { + try { + res.writeHead(200,{ + 'Content-Type': 'text/plain' + }); + res.write(cowsay.say({ + text: req.body.text + })); + return res.end(); + } catch (err) { + res.writeHead(400); + res.write(cowsay.think({ + text: 'Bad Request. Daemon is happy. Try again.', + f: 'daemon' + })); + return res.end(); + } + } + return res.end(); + }); + } +}); + +server.listen(PORT, () => { + console.log('server is up:', PORT); +});