Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d0e9d14
adds readme and package.json
lizzkats Mar 20, 2017
58ce6e9
adds testing and some modulating operations
lizzkats Mar 21, 2017
1a2f2b8
modulated routing, completed search query
Mar 21, 2017
1309d17
completed sandbox api and created postalicious directories
Mar 21, 2017
abd9298
Merge pull request #1 from lizzkats/sandbox-server
lizzkats Mar 21, 2017
9ad607e
added start scripts
lizzkats Mar 21, 2017
5ece442
adding untracked file
lizzkats Mar 21, 2017
fd20a04
gitignore
lizzkats Mar 21, 2017
cea430c
added basic form on front end
lizzkats Mar 22, 2017
3bd80e3
Merge pull request #2 from lizzkats/postalicious-server
lizzkats Mar 22, 2017
8df60d0
established form data extraction
Mar 22, 2017
9d531f8
added css styling, layout corrections, data retrieval
Mar 23, 2017
857657c
Merge pull request #3 from lizzkats/postal
Mar 23, 2017
983c5cd
missing files
Mar 23, 2017
9a0d9a3
method file
Mar 23, 2017
a15c88e
adds some UI for requests
lizzkats Mar 23, 2017
caedce8
gettin that fetch done
Mar 23, 2017
cd36d84
getting a response back and adding default input values
lizzkats Mar 24, 2017
5ff5841
completed parsing of http response from sandbox server
Mar 24, 2017
fbd53d7
Merge pull request #4 from lizzkats/fetching
Mar 24, 2017
f7c406a
fixes UI and spacing
lizzkats Mar 24, 2017
a88520b
cleaned up console logs and commented code
Mar 24, 2017
027f014
Merge pull request #6 from lizzkats/broom
Mar 24, 2017
b5394f7
Merge pull request #5 from lizzkats/UIfix
Mar 24, 2017
1b77644
Update README.md
lizzkats Mar 25, 2017
e282559
Update README.md
lizzkats Mar 26, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
*log
102 changes: 101 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,102 @@
# Postalicious
A clone of the Postman chrome extension
A clone of the Postman app.

## Description
See http://jsdev.learnersguild.org/goals/194-Postalicious-Demystifying_HTTP.html for description.


- [x] The artifact produced is a repo with at least two sub-folders: postalicious/ and sandbox-server/.
- [x] The artifact produced is properly licensed, preferably with the MIT license.

## Sandbox Server

- [x] Can run the command npm run sandbox-server (or npm run sb, if you want to save some typing) to start the sandbox web server at port 3000.
- [x] The sandbox server source code is written using the Express library.
- [x] Sending a GET request to the path / responds with
- [x] a 200 (OK) status code a plain-text response
- [x] body with the content Welcome to Sandbox!
- [x] the Content-Type header set to text/plain
- [x] Sending a GET request to the path /search?q=doodads responds with
- [x] a 200 (OK) status code
- [x] a plain-text response body with the content You searched for: "doodads" (it doesn’t need to actually do any searching, just return the plain text)
- [x] the Content-Type header set to text/plain
- [x] Sending a GET request to the path /search responds with…
- [x] a 400 (Bad Request) status code
- [x] a plain-text response body with the content You didn't provide a search query term :(
- [x] the Content-Type header set to text/plain
- [x] Sending a POST request to the path /things with a plain text body flying car responds with…
- [x] a 201 (Created) status code
- [x] a plain-text response body with the content New thing created: "flying car"! (it doesn’t need to actually create anything, just return the plain text)
- [x] the Content-Type header set to text/plain
- [x] Sending a GET request to the path /somefile with an Accept header of text/plain responds with…
- [x] a 200 (OK) status code
- [x] a plain-text response body with the content This is a plain text file
- [x] the Content-Type header set to text/plain
- [x] Sending a GET request to the path /somefile with an Accept header of text/html responds with…
- [x] a 200 (OK) status code
- [x] an HTML response body with the content <!DOCTYPE html><html><body>This is an HTML file</body></html>
- [x] the Content-Type header set to text/html
- [x] Sending a GET request to the path /myjsondata with an Accept header of application/json responds with…
- [x] a 200 (OK) status code
- [x] an HTML response body with the content { "title": "some JSON data" }
- [x] the Content-Type header set to application/json
- [x] Sending a GET request to the path /old-page responds with…
- [x] a 301 (Moved Permanently) status code
- [x] the Location header set to http://localhost:3000/newpage
- [x] Sending a POST request to the path /admin-only responds with a 403 (Forbidden) status code
- [x] Sending a GET request to the path /not-a-page responds with a 404 (Not Found) status code
- [x] Sending a GET request to the path /server-error responds with a 500 (Internal Server Error) staus code


##Postalicious

- [x] Can run the command npm run postalicious (or npm run pl, if you want to save some typing) to start the Postalicious app at port 3001.
- [x] Users can visit the main page of the Postalicious site at http://localhost:3001.
- [x] Main page has three main sections:
- [x] Request builder HTML form
- [x] Raw HTTP request
- [x] Raw HTTP response
- [x] When a user fills out the HTML form and clicks a “Send” button…
- [x] The raw HTTP request is generated and shown
- [x] The HTTP request is sent, and the raw response message is shown
- [x] Users can fill out an HTML form to specify HTTP request details.
- [x] Submitting the form will send the request according to the specified details.
- [x] Using the HTML form, users can specify…
- [x] host and path
- [x] HTTP verb/method
- [x] query parameter keys + values
- [x] header keys + values
- [x] request body

##Stretch

Use the stretch goals to go deeper into the nuts and bolts of HTTP.

- [ ] Sandbox server is written using only the core Node.js modules (instead of Express, use the built-in HTTP module).
- [ ] Users of Postalicious can “save” their requests in a history panel
- [ ] Clicking on a saved request will re-load it into the form
- [ ] Using Postalicious, create some HTTP requests to various real-world APIs:
- [ ] Get all issues for a repo through the GitHub API
- [ ] Get all tweets with the hashtag #javascript with the Twitter API
- [ ] Any other API request(s) of your choice
- [ ] External HTTP requests are saved in files under a example-requests/ directory (make sure to obscure any secure information before saving these files, like your password or authentication token)

##Quality Rubric

* Well formatted code

* Code uses a linter, which can be invoked with a command (e.g. npm run lint). [50 points]
* Running the linter on all source code files generates no linting errors. [50 points]
* Clear and useful README

* Repository includes a README file with installation and setup instructions. [25 points]
* Repository includes a README file with usage instructions and at least one example use case. [25 points]
* Proper dependency management

* There is a command to install dependencies (e.g. npm install) and it is specified in the installation and setup instructions of the README. [50 points]
* Good project management

* Commit messages are concise and descriptive. [25 points]
* All features are added via pull requests. [25 points]
* Every pull request has a description summarizing the changes made. [25 points]
* Every pull request has been reviewed by at least one other person. [25 points]
34 changes: 34 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "postalicious",
"version": "1.0.0",
"description": "A clone of the Postman chrome extension.",
"main": "index.js",
"scripts": {
"sandbox-server": "nodemon sandbox-server/index",
"pl": "nodemon postalicious/index",
"test": "mocha sandbox-server/test/sandbox_tests.js",
"testTwo:": "mocha postalicious/test/post_tests.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/lizzkats/Postalicious.git"
},
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/lizzkats/Postalicious/issues"
},
"homepage": "https://github.com/lizzkats/Postalicious#readme",
"dependencies": {
"body-parser": "^1.17.1",
"express": "^4.15.2",
"morgan": "^1.7.1"
},
"devDependencies": {
"chai": "^3.5.0",
"chai-http": "^3.0.0",
"cors": "^2.8.1",
"mocha": "^3.2.0",
"pg-promise": "^5.6.4"
}
}
22 changes: 22 additions & 0 deletions postalicious/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const express = require('express')
const server = express()
const http = require('http').createServer(server)
const path = require('path')
const logger = require('morgan')
const bodyParser = require('body-parser')

const port = process.env.PORT || 3001
const index = require('./routes/form_routes.js')

server.use(bodyParser.json({ type: 'application/json' }))
server.use(bodyParser.urlencoded({extended: true}))
server.use(express.static(path.join(__dirname, 'public')))
server.use('/', index)

server.use(logger("combined"))

server.set(port)

http.listen(port)

module.exports = server
100 changes: 100 additions & 0 deletions postalicious/public/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Postalicious</title>
<link rel='stylesheet' href='../stylesheets/style.css'>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Lobster" rel="stylesheet">
</head>
<body>
<div style="margin:auto;width:100%;text-align:center;">
<div class="container-fluid" style="padding-right: 0px;padding-left: 0px;margin-right: 0px;margin-left: 0px;">
<div class="title" style="font-size:3em;font-family:'Lobster', cursive;text-align:center;width:100.8%;"> Postalicious </div>
<div class="container-fluid" style="margin: 0 auto; width: 65%;">
<div class="col-xs-3" style="width:300px;">
<div class="row" style="width: 280px;">
<span class="method">Method</span>
<select class="method-input">
<option value="GET">GET</option>
<option value="POST">POST</option>
</select>
</div>
<div class="row" style="width: 280px;">
<span class="host" >Host</span>
<input type="text" value="http://localhost:3000" class="host-input"></input>
</div>
</div>
<div class="col-xs-2" style="width: 350px;">
<span>Query Parameters</span>
<div class="row" style="width:400px;">
<div class="col-xs-4" style="width:155px;">
<input type="text" class="key" name="query-option" placeholder ="key"></input>
<input type="text" class="key" name="query-option2" placeholder ="key"></input>
<input type="text" class="key" name="query-option3" placeholder ="key"></input>
</div>
<div class="col-xs-4" style="width:155px;">
<input type="text" class="value" name="query-option4" placeholder ="value"></input>
<input type="text" class="value" name="query-option5" placeholder ="value"></input>
<input type="text" class="value" name="query-option6" placeholder ="value"></input>
</div>
</div>
</div>
<div class="col-xs-3" style="width: 350px;">
<span class="headers" style="">Headers</span>
<div class="row" style="width:400px;float">
<div class="col-xs-4" style="width:155px;">
<input type="text" id="header-key1" name="header-option" value="content-type" placeholder ="key"></input>
<input type="text" id="header-key2" name="header-option2" value="Accept" placeholder ="key"></input>
<input type="text" id="header-key3" name="header-option3" value="Accept-Charset" placeholder ="key"></input>
</div>
<div class="col-xs-4" style="width:155px;">
<input type="text" id="header-value1" name="header-option4" value="text/plain" placeholder ="value"></input>
<input type="text" id="header-value2" name="header-option5" value="text/plain" placeholder ="value"></input>
<input type="text" id="header-value3" name="header-option6" value="utf-8" placeholder ="value"></input>
</div>
</div>
</div>
<span class="body">Body</span>
<input type="text" id="request_body" name="request-body" class="body-box"></input>
<div class="col-xs-3" style="width:11%;">
</div>
</div>
</div>
</div>
<div class="container-fluid" style="padding-right: 0px;padding-left: 0px;margin-right: 0px;margin-left: 0px;">
<div class="row" style="width:67%;">
<div class="build-button">
<div class="col-xs-6" style="margin-left:778px;width:11%;">
<button onclick="construct(event)" class="build-send">Build &amp; Send </button>
</div>
</div>
<div class="request-button" style="display:inline-block;width:180px;margin-left:55px;">
<button onclick="build(event)" class="build-request">Build Request</button>
</div>
</div>
<div class="row">
<div class="col-xs-6" style="width:50%;background-color:#00cc00;">
<div class="request-body-box" type="text"><div style="background-color:#009900; width:191.9%;font-weight:bolder;justify-content:center;">
REQUEST
</div>
<div id="request-info" style="margin-left: 419px; text-align: left;">
<div id="request_content"></div>
<div id="request_content2"></div>
<div id="request_content3"></div>
</div>
</div>
</div>
<div class="response" style="width:50%;background-color:#0099ff;float:right">
<div class="response-body-box" type="text"><div style="background-color:#0066cc; width:196.9%;font-weight:bolder;">
RESPONSE
</div>
<div id="response-info2" style="height:23%;width:100%;text-align:left;margin-left:395px"></div>
<div id="response-info1" style="height:15%;width:100%;text-align:left;margin-left:395px"></div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="methods.js"></script>
</body>
</html>
108 changes: 108 additions & 0 deletions postalicious/public/methods.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
const protocol = 'http/1.1'
const method = document.getElementsByClassName("method-input")[0].value
const docKeyLength = document.getElementsByClassName("key").length
const docValLength = document.getElementsByClassName("value").length

function construct(event) {
event.preventDefault()
const host = document.getElementsByClassName("host-input")[0].value
const keyHeader1 = document.getElementById('header-key1').value
const valueHeader1 = document.getElementById('header-value1').value
const keyHeader2 = document.getElementById('header-key2').value
const valueHeader2 = document.getElementById('header-value2').value
const keyHeader3 = document.getElementById('header-key3').value
const valueHeader3 = document.getElementById('header-value3').value
const bodyBox = document.getElementById('request_body').value
let responseHeaders = []
let responseHeaderValues = []
let headersAndValues = []
let status, statusText
let init = {}

if(keyHeader1.length === 0){
init[keyHeader1] = valueHeader1
}
if(keyHeader2.length === 0){
init[keyHeader2] = valueHeader2
}
if(keyHeader3.length === 0){
init[keyHeader3] = valueHeader3
}

let url = ''
url += host
if(document.getElementsByClassName("key")[0].value.length !== 0){
url +='?'
for (var i = 0; i < docKeyLength - 1; i++) {
if(document.getElementsByClassName("key")[i].value.length !== 0){
url += uriEncondingComponent(document.getElementsByClassName("key")[i].value) + '=' + uriEncondingComponent(document.getElementsByClassName("value")[i].value + '&')
}
}
url = url.substring(0, url.length - 1)
}

let myRequest = new Request(url)
myRequest.body = bodyBox

fetch(myRequest)
.then(response => {
document.getElementById("response-info1").innerText = 'status: ' + response.status + '\n' +'statusText: ' + response.statusText
return response.blob()
}).then(result => {
var reader = new FileReader();
reader.addEventListener("loadend", function() {
if(result.type === 'application/json') {
//TODO:
}
if(result.type === 'text/plain'){
let output = ''
output += reader.result + '\n'
output += 'content-type: ' + result.type + '\n'
output += 'content-length: ' + result.size + '\n'
document.getElementById("response-info2").innerText = output
}
})
reader.readAsText(result);
})

document.getElementById("request_content").innerText = method + ' ' + protocol
document.getElementById("request_content2").innerText = url
}
function build(event) {
event.preventDefault()
const host = document.getElementsByClassName("host-input")[0].value
const keyHeader1 = document.getElementById('header-key1').value
const valueHeader1 = document.getElementById('header-value1').value
const keyHeader2 = document.getElementById('header-key2').value
const valueHeader2 = document.getElementById('header-value2').value
const keyHeader3 = document.getElementById('header-key3').value
const valueHeader3 = document.getElementById('header-value3').value
const bodyBox = document.getElementById('request_body').value

let init = {}

if(keyHeader1.length === 0){
init[keyHeader1] = valueHeader1
}
if(keyHeader2.length === 0){
init[keyHeader2] = valueHeader2
}
if(keyHeader3.length === 0){
init[keyHeader3] = valueHeader3
}

let url = ''
url += host
if(document.getElementsByClassName("key")[0].value.length !== 0){
url +='?'
for (var i = 0; i < docKeyLength - 1; i++) {
if(document.getElementsByClassName("key")[i].value.length !== 0){
url += uriEncondingComponent(document.getElementsByClassName("key")[i].value) + '=' + uriEncondingComponent(document.getElementsByClassName("value")[i].value + '&')
}
}
url = url.substring(0, url.length - 1)
}

document.getElementById("request_content").innerText = method + ' ' + protocol
document.getElementById("request_content2").innerText = url
}
Loading