Last active
February 3, 2021 03:32
-
-
Save skawnkk/b499f559fffa7d524e44645a54101e1a to your computer and use it in GitHub Desktop.
http
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment