# Back-end basics - HTTP / Node.js / npm
## 為何要分前後端?
**前端**:client端,處理簡單的使用者體驗
**後端**:server端,負責龐大**複雜的運算**(使用者體驗效能)&有**商業機密**的演算法邏輯
client端若遇到龐大的運算(e.g. 手機cpu跑不動)或商業機密演算法(e.g. Google搜尋功能),送出request給server端處理,有主從關係
## HTTP (HyperText Transfer Protocol)
1. a format of communication between two devices over the internet
2. Stateless
#### HTTP Requests Using Telnet
* Installing Telnet Client - OSX
If you're using a Mac, Telnet should be installed and enabled. Simply open a terminal and execute some of the commands used in this video.
* Installing Telnet Client - Windows
Depending on your version of Windows, you may already have it installed, and you simply need to enable it. Opening PowerShell and attempting to use Telnet will reveal whether or not you'll need to install.
[Install Telnet on Windows](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2008-R2-and-2008/cc771275(v=ws.10)?redirectedfrom=MSDN#bkmk_installcmd)
[Enable Telnet on Windows](https://www.rootusers.com/how-to-enable-the-telnet-client-in-windows-10/)
* HTTP Request Format

* HTTP Response Format

200:ok | 400s:something went wrong 404:not found | 300s:resources moved | 500s:server error
#### Sending Data with a GET Request
GET requests are read-only request.
```
GET /books?type=kindle&sort=popular HTTP/1.1
Host: amazon.com
Accept-Language: en-US
```
1. requesting a resource at `/books`
2. when using a [query string](https://www.techopedia.com/definition/1228/query-string) and a [URI](https://danielmiessler.com/study/difference-between-uri-url/), started with `?`
3. passing a `type=kindle` and `sort=popular` in a form *(name value pairs)* of query string, seperated with `&`


in a *get request*, additional data related to your requested resource is passed as a *query string* in the URI.
#### Sending Data with a POST Request
POST requests are used for sending a request whose purpose is to modify data on the server.
```
POST /register HTTP/1.1
Host: example.com
Accept-Language: en-US
Connection: keep-alive
Content-Length: 30
name=Sara&email=sara@tmail.com
```
1. In a POST request, data is sent in the request body/payload instead of in the URI.
2. Content-Length要跟payload裡的byte數一致
3. 一個空行把header跟payload分開
4. *query string*寫在payload裡,byte數不一致會導致400:bad request
### The Browser as a GUI for HTTP


#### Using Forms for GET Requests
```
<form method="get" action="/search">
<input type="text" name="q">
<button type="submit">Search</button>
</form>
```
1. form tags `<form> </form>`
2. form method attribute - optional, defaults to "get" `method="get"`
3. form action attribute `action="/search"`
4. form elements for users to provide info `<input type="text" name="q">`
5. submit button - optional, triggered with ENTER `<button type="submit"> </button>`





#### Using Forms for POST Requests
HTML Forms with File Uploads
1. An input element with the type "file" is added, and
2. The encoding type of the form element must be set to "multipart/form-data"
```
<form method="post" action="/update_profile" enctype="multipart/form-data">
<input type="text" name="handle">
<input type="file" name="avatar">
<button type="submit">Upload</button>
</form>
```
When the form is submitted, the request looks something like the following:
1. `Content-Type` and `Content-Length` are required in the header.
2. payload after a blank bar
3. Notice that the data is transmitted in parts, which explains the "multipart/form-data" encryption type of the form, as well as the resulting and identical content-type header.
```
POST /update_profile HTTP/1.1
Content-Type: multipart/form-data; boundary=----TH23XJ
Content-Length: 34209
------TH23XJ
Content-Disposition: form-data; name="handle"
treehouse
------TH23XJ
Content-Disposition: form-data; name="avatar"; filename="me.jpg"
Content-Type: image/jpeg
[binary data of file]
------TH23XJ
```



[計算query string的bytes數](https://charcounter.com/zh/)

### Where to Go From Here
1. [HTTP response codes](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes)
2. Cookies
3. SSL/HTTPS
4. Other request methods (such as PUT and DELETE)
5. REST API
## Node.js
Node.js® is an open-source, cross-platform, asynchronous event-driven JavaScript **runtime environment**.
[Netflix case study](https://openjsf.org/blog/2020/09/24/from-streaming-to-studio-the-evolution-of-node-js-at-netflix/) | [Case Study Node.js & NASA](https://openjsf.org/wp-content/uploads/sites/84/2020/02/Case_Study-Node.js-NASA.pdf) | [A Brief Explanation of the JavaScript Engine and Runtime](https://dev.to/sanderdebr/a-brief-explanation-of-the-javascript-engine-and-runtime-2idg) | [JSONView插件](https://jsonview.com/) | [node doc](https://nodejs.org/api/documentation.html)
front-end runtime enviorment: chrome(browser)
back-end runtime enviorment: node(server-side JS)

* Running a node application
```
node <filename>
```
* Running the node REPL (Read-Eval-Print-Loop)
```
node //To exit the REPL use CTRL+D once or CTRL+C twice.
```
### Requesting data with **https** (Node.js' built in modules) 5個步驟
User Events - triggered by user input ('click', 'hover', 'scroll')
System Events - triggered by machine ('setTimeOut')
* Data
* Completion
* Errors
#### require() 引入模組
```
//1.引入node內建https模組
const https = require("https");
```
#### get method 從api取得資料並處理
```
//參數1:api網址 參數2:處理response的callback
https.get('url', (reponse)=>{...})
```
* 有些API需要取得API key才可以使用,使用query string傳入
```
//query string
`url?key=267fc1f6-64b2-4cba-b6ec-308de21c2a6b`
```
#### console.dir()
```
//display object properties in a list
console.dir(object)
```

#### on method (類似addEventListener)
```
//參數1:event 參數2:當event發生時執行的callback
response.on("data", (data) => {...});
```
* data event: occurs when data is received by our program
* end event: when there is no more data to be consumed from the *stream*
* error event: occurs when errors
### 處理回傳的資料
* Buffers
on method 會return一大串binery data, Large amount of binary data are called **stream**s, can be stored using **Buffers**.但人無法閱讀
* 用 `toString()` 和 `JSON.parse()` 處理資料
```
function getDef(term) {
try {
// 2.Connect to the API URL (根據輸入的使用者查詢資料)
const request = https.get(
`https://dictionaryapi.com/api/v3/references/collegiate/json/${term}?key=267fc1f6-64b2-4cba-b6ec-308de21c2a6b`,
(response) => {
let body = "";
// 3.載入binary資料, make it readable
response.on("data", (data) => {
body += data.toString(); //把傳入的資料都處理成字串
});
//4.等資料都傳入後執行
response.on("end", () => {
const definition = JSON.parse(body); //把字串處理成 JSON object
console.log(definition[0].shortdef); //Print the data
});
}
);
request.on("error", (error) => console.error(error.message)); //6.error發生時載入error資料
} catch (error) { //7.用try...catch 處理bad argument事件
console.error(error.message);
}
}
```
#### Process Object (類似 window object in browser)
Node's own global object, contains info about the location of Node on your computer.(file being executed and any arguments we enter at execution.)
```
console.dir(process); //log out info about the location of Node
```
```
//5.取用並處理process.argv的資料
const query = process.argv.slice(2) //用slice()只取array of arguments we enter cmd
query.forEach(getDef); //用array.forEach()個別將arguments傳入function並執行
```
* argv
process's property give us the array of [0]*node binary file*, our [1]*app.js* and contains an [2...end]*array of arguments we enter into the command line*.
### The error event in Node
#### Error object
* **types** of error:
Standard JS errors
System Errors
User-specified
Assertion
* **error.stack** - error location
* **error.code** - kind of error
* **error.message** - string description
#### bad argument事件 (Capture Synchronous Errors with [Try Catch](https://ithelp.ithome.com.tw/articles/10208079))
通常由 *程式碼出錯*, *missing protocol*, *invalid URL* 或 *parsing error* 造成, Asyncronous call cannot be made so this error is Syncronous.
這種狀況下program將沒辦法運行,因此可以使用**try...catch block** in Node.
* parsing error: 例如run program with fake term,就像在尋找不存在的檔案,會return an invalid response, which will cause an error when JSON.parse()

* Handle Status Code Errors
```
const http = require("http");
const message = `There was an error getting the profile for ${username} (${
http.STATUS_CODES[response.statusCode]
})`;
const statusCodeError = new Error(message);
printError(statusCodeError);
```
## npm
[NPM](http://npmjs.com/) is a **command line package manager** installed with Node, npm packages for Node.js projects are called **modules**.
* npm Package Examples
[Accessibility-developer-tools](https://www.npmjs.com/package/accessibility-developer-tools) | [Express](http://expressjs.com/) | [Passport](http://passportjs.org/) | [jQuery Plugins](https://www.npmjs.com/browse/keyword/jquery-plugin) - [tipso](https://www.npmjs.com/package/tipso) | [Grunt](http://gruntjs.com/) | [gulp.js](http://gulpjs.com/) | [CoffeeScript](http://coffeescript.org/) | [TypeScript](http://www.typescriptlang.org/) | [Sass](http://sass-lang.com/) | [Cordova](http://cordova.apache.org/) | [PhoneGap](http://phonegap.com/) | [Ionic](http://ionicframework.com/) | [johnny-five](http://johnny-five.io/) | [Espruino](http://www.espruino.com/) | [Tessel](https://tessel.io/) | [nodemon](https://www.npmjs.com/package/nodemon) | [http-server](https://www.npmjs.com/package/http-server)
* Node.js and npm Install Guides
[Mac](http://treehouse.github.io/installation-guides/mac/node-mac.html) | [Windows](http://treehouse.github.io/installation-guides/windows/node-windows.html) | [Linux](http://treehouse.github.io/installation-guides/linux/node-linux.html)
#### Choosing Packages
There are a number of indicators that you can use to determine which package to use.
* Popularity on npm_ – the number of downloads
* Release Date – the more recent the better
* Number of Releases – the more frequent the better
* Passing Tests - if there's tests passing
* Number of Open Issues – the less the better
* Popularity on GitHub – The more Stars, Forks and Watches the better
* Number of Contributors on GitHub – more eyes on the code the better
#### [Semantic Versioning](https://semver.org/)
a system for communicating changes in versions of projects
[npm semver calculator](https://semver.npmjs.com/)
* `MAJOR.MINOR.PATCH`
Major: most important to watchoutfor, may require refactoring.
Minor:typically won't affect your apps.
Patch:Bug fixes are usually beneficial and shouldn't have any other effects on your apps.
#### npm Command Line Usage
* See list of commands `npm`
* Installing a packages from package.json `npm install`
#### Installing Packages & Managing Dependencies
* Get help for a command `npm <command> -h`
* Installing a global package: creating multiple project with package `npm install <package_name> -g`
* Installing a local package: a project depends on this package `npm install <package_name>`
* Installing a specific version: `npm install <package_name@version>`
[Example: installing Express](https://expressjs.com/en/starter/installing.html) | [Fixing npm Permission Issues](https://docs.npmjs.com/resolving-eacces-permissions-errors-when-installing-packages-globally)
1. Use the `npm init` command to create a package.json file for your application.
2. 填寫package.json資料 (`npm init -y` for default 資料,免填寫)
3. `npm install <package_name>`
4. npm會創建**package.json**,裡面的dependencies紀錄project需要的package(第一次安裝時的版本,不會紀錄更新版本)

* **package-lock.json**紀錄更多package細節,包括實際上安裝的更新版本
5. 設定git [Ignoring files](https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files) 來避免模組包被上傳到github
[A collection of useful .gitignore templates](https://github.com/github/gitignore) 
#### Updating, Uninstalling and Executing Packages
* Check for outdated packages `npm outdated`
* Update packages in your project
For local packages `npm update`
For global packages `npm update <package name> -g`
* Uninstalling packages
Uninstall a local dependency `npm uninstall <package name>`
Uninstall a global dependency `npm uninstall <package name> -g`
* [The `npx` Node Package Runner](https://www.npmjs.com/package/npx): allows you to run packages whether they are installed locally or not.適合一次性的package ex: [Express-generator](https://www.npmjs.com/package/express-generator), [Creat react app](https://create-react-app.dev/)