Skip to content

Instantly share code, notes, and snippets.

@skawnkk
Last active February 3, 2021 03:32
Show Gist options
  • Save skawnkk/b499f559fffa7d524e44645a54101e1a to your computer and use it in GitHub Desktop.
Save skawnkk/b499f559fffa7d524e44645a54101e1a to your computer and use it in GitHub Desktop.
http
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
const chalk = require('chalk');
const title = chalk.yellowBright
const dns = require('dns');
const dnsPromises = dns.promises;
const net = require('net');
class HttpResponse {
send(chunk) {
new Promise((resolve) => {
resolve(this.print(chunk))
}).then(setTimeout(this.close, 3000))
}
print(chunk) {
let responseMsg = chunk.toString();
let statusLine = responseMsg.split("\r\n\r\n")[0].split('\r\n')[0];
let headers = responseMsg.split("\r\n\r\n")[0].split('\r\n').slice(1).join('\r\n');
let messageBody = responseMsg.split("\r\n\r\n")[1];
console.log(title('[HTTP Response - HEADER]\n'), `${statusLine}\n${headers}`)
console.log(title('\n[HTTP Response Body - HTML]\n'), messageBody)
}
close() {
console.log(title('[Server ends]'), 'BYE~');
process.exit();
}
}
class HttpRequest extends HttpResponse {
constructor(url) {
super()
this.url = url;
this.domain = this.url.host;
this.port = 80;
this.socket = new net.Socket();
this.address;
this.promise = dnsPromises;
this.server = new HttpResponse();
this.method = 'GET';
this.index = '/';
this.httpVersion = '1.1';
}
getIPaddress() {
this.promise.lookup(this.domain).then((result) => {
let printIP = `url: ${this.domain}\n (DNS lookup...)\nTCP Connection: ${result.address} ${this.port}`;
console.log(title('\n[DNS_Server_Request]\n'), printIP)
this.address = result.address;
this.connect(this.address);
console.log("*socketState:", this.socket.readyState) //opening
})
}
connect(address) {
const self = this;
this.socket.connect(this.port, this.address, function () { //this->self로 선언
const linked = self.socket.write(`${self.msg(self.method, self.index, self.httpVersion, self.address)}`) //'write' :Sends data on the socket
console.log("*socketState:", self.socket.readyState) //open
/*연결상태를 확인하는 방법
1. console.log(linked) //Returns true if the entire data was flushed successfully to the kernel buffer.
2. self.socket.on('ready', function () { //'ready':연결됬음을 확인시켜준다.
console.log('▶ Hello Server :) ')
})
3. console.log(self.socket.readyState) //open
Value State Description
0 CONNECTING 소켓이 생성되었다. 연결이 아직 열려 있지 않다.
1 OPEN 연결이 열려 있고, 통신할 준비가 되었다.
2 CLOSING 연결이 닫히는 중이다.
3 CLOSED 연결이 닫혔거나 열 수 없었다.*/
self.socket.on('data', function (chunk) {
self.server.send(chunk) //'data': Emitted when data is received.
})
self.socket.on('error', function (error) {
console.log(title('Error!'));
self.socket.destroy();
console.log("\n*socketState:", self.socket.readyState) //close
self.server.close();
//'destroy': Ensures that no more I/O activity happens on this socket. Destroys the stream and closes the connection.
//[What is TCP FIN PACKET?]https://ipwithease.com/what-is-tcp-fin-packet/
})
})
}
msg(method = 'GET', index = '/', httpVersion = '1.1', address) {
const requestLine = `${method} ${index} HTTP/${httpVersion}\r\n`;
const requestHeader = `Host:${address}\r\nConnection: keep-alive`;
const requestMsg = requestLine + requestHeader + '\r\n\r\n';
console.log(title('\n[HTTP Request]\n'), requestMsg);
return requestMsg;
}
//'\r\n\r\n :
// GET요청의 경우 별도의 요청내용인 바디가 없음.
//요청에 대한 모든 메타 정보가 전송되었음을 알리는 빈 줄(blank line)이 삽입됩니다.
//헤더의 종료를 마지막 빈 줄로 표시해준다.
}
//*url주소 입력
const urls = [
'http://www.hani.co.kr', //failure
'http://www.disney.co.kr', //200
'http://www.naver.com', //302
/*302 found :클라이언트가 요청한 리소스가 Location 헤더에 주어진 URL에 일시적으로 이동되었음을 가리킨다.
http요청 ->https로 전환, 브라우저는 사용자를 이 URL의 페이지로 리다이렉트시키지만
검색 엔진은 그 리소스가 일시적으로 이동되었다고 해서 그에 대한 링크를 갱신하지는 않는다 */
'http://www.khan.co.kr', //400
'http://www.yes24.com', //404
'http://www.kyobobook.co.kr' //200
];
console.log(title('[url_List]'))
for (let key of urls.keys()) {
console.log(`${key+1}: ${urls[key]}`)
}
rl.question(title("CHOICE URL ADREESS >"), (answer) => {
const url = new URL(urls[parseInt(answer) - 1])
const client = new HttpRequest(url)
client.getIPaddress()
})
와이어샤크 실행

shark1
shark2

코드 실행

vscode

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment