node.js - http, express (210224)
nodejs
http client
= 브라우저 기능
= 크롤링(스크래핑)
1. ajax / 로그인 (o)
phantomjs + setTimeout
getElementById
2. ajax / 로그인 (x)
urllib / axios
*dom 처리
string
cheerio
http server
= tomcat + servlet
1. http.createServer().listen(포트번호)
2.
let parseUrl = new URL( req.url );
parseUrl.pathname = ??
3. post / get
=> framework
새로 작업할 폴더를 생성
mkdir httpex2
cd httpex2
npm init -y
mkdir public_html
touch public_html/gugudan.html
touch public_html/gugudan_ok.html
touch public_html/error.html
code
open folder
gugudan 소스
기본 네비게이터
브라우저에 url로 접속해서 각 페이지로 이동하는 기본구조
// server1.js
"use strict";
const http = require( 'http' );
const fs = require( 'fs' );
const url = require( 'url' );
// server
const server = http.createServer( (req, res ) => {
// controller
let parseUrl = url.parse( req.url, true );
if( parseUrl.pathname == '/gugudan' ) {
fs.createReadStream( './public_html/gugudan.html' ).pipe( res );
} else if( parseUrl.pathname == '/gugudan_ok' ) {
fs.createReadStream( './public_html/gugudan_ok.html' ).pipe( res );
} else {
fs.createReadStream( './public_html/error.html' ).pipe( res );
}
}).listen( 8080, () => {
console.log( '8080 포트에서 요청 대기중 ...' );
});
각 페이지의 html파일
<!-- gugudan.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>gugudan.html</h1>
<form action="./gugudan_ok" method="get">
dan : <input type="text" name="dan" />
<input type="submit" value="전송" />
</form>
</body>
</html>
<!-- gugudan_ok.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>gugudan_ok.html</h1>
<hr /><br />
${ result }
</body>
</html>
<!-- error.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>error.html</h1>
</body>
</html>
gugudan => get방식
// server1.js
"use strict";
const http = require( 'http' );
const fs = require( 'fs' );
const url = require( 'url' );
// server
const server = http.createServer( (req, res ) => {
// controller
let parseUrl = url.parse( req.url, true );
if( parseUrl.pathname == '/gugudan' ) {
fs.createReadStream( './public_html/gugudan.html' ).pipe( res );
} else if( parseUrl.pathname == '/gugudan_ok' ) {
if( req.method.toLocaleLowerCase() == 'get' ) {
let query = parseUrl.query;
//let result = query.dan;
let result = '<table width="800" border="1">';
result += '<tr>';
for( let i=1; i<=9; i++ ) {
result += '<td> ' + query.dan + ' X ' + i + ' = ' + ( parseInt(query.dan) * i ) + '</td>';
}
result += '</tr>';
result += '</table>';
const html = fs.readFileSync( './public_html/gugudan_ok.html' );
const tplHtml = eval( '`' + html.toString().replace( /`/g, '\\`' ) + '`' );
res.end( tplHtml );
}
} else {
fs.createReadStream( './public_html/error.html' ).pipe( res );
}
}).listen( 8080, () => {
console.log( '8080 포트에서 요청 대기중 ...' );
});
실행결과
get방식에서는 ?dan=6이 url에 추가됨
gugudan => post 방식
// server2.js
"use strict";
const http = require( 'http' );
const fs = require( 'fs' );
const url = require( 'url' );
const querystring = require( 'querystring' );
// server
const server = http.createServer( (req, res ) => {
// controller
let parseUrl = url.parse( req.url, true );
if( parseUrl.pathname == '/gugudan' ) {
fs.createReadStream( './public_html/gugudan.html' ).pipe( res );
} else if( parseUrl.pathname == '/gugudan_ok' ) {
if( req.method.toLocaleLowerCase() == 'post' ) {
let buffer = '';
req.on( 'data', chuck => {
buffer += chuck;
});
req.on( 'end', () => {
const query = querystring.parse( buffer );
//let result = query.dan;
let result = '<table width="800" border="1">';
result += '<tr>';
for( let i=1; i<=9; i++ ) {
result += '<td> ' + query.dan + ' X ' + i + ' = ' + ( parseInt(query.dan) * i ) + '</td>';
}
result += '</tr>';
result += '</table>';
const html = fs.readFileSync( './public_html/gugudan_ok.html' );
const tplHtml = eval( '`' + html.toString().replace( /`/g, '\\`' ) + '`' );
res.end( tplHtml );
});
}
} else {
fs.createReadStream( './public_html/error.html' ).pipe( res );
}
}).listen( 8080, () => {
console.log( '8080 포트에서 요청 대기중 ...' );
});
실행결과
get방식과 결과는 같지만 url에 추가로 query가 붙지 않음
우편번호 검색
zipsearch public_html/zipsearch.html
zipsearch_ok public_html/zipsearch_ok.html
기타 public_html/error.html
기본설정
mkdir zipsearchex1
cd zipsearchex1/
npm init -y
npm install mariadb // mariadb와 연동해서 사용하므로 꼭 추가
mkdir public_html
touch public_html/error.html
touch public_html/zipsearch_ok.html
touch public_html/zipsearch.html
zipsearch => post 방식
html 파일들 소스
<!-- zipsearch.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>zipsearch.html</h1>
<form action="./zipsearch_ok" method="post" >
동이름 : <input type="text" name="dong" />
<input type="submit" value="전송" />
</form>
</body>
</html>
<!-- zipsearch_ok.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>zipsearch_ok.html</h1>
${ result }
</body>
</html>
<!-- error.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>error.html</h1>
</body>
</html>
우편번호 검색기
// server.js
"use strict";
const http = require( 'http' );
const fs = require( 'fs' );
const url = require( 'url' );
const querystring = require( 'querystring' );
const mariadb = require( 'mariadb/callback' );
const server = http.createServer( (req, res ) => {
let parseUrl = url.parse( req.url, true );
if( parseUrl.pathname == '/zipsearch' ) {
fs.createReadStream( './public_html/zipsearch.html' ).pipe( res );
} else if( parseUrl.pathname == '/zipsearch_ok' ) {
if( req.method.toLocaleLowerCase() == 'post' ) {
let buffer = '';
req.on( 'data', chuck => {
buffer += chuck;
});
req.on( 'end', () => {
const query = querystring.parse( buffer );
//let result = query.dong;
const conn = mariadb.createConnection( {
host: 'localhost',
user: 'root',
password: '!123456',
database: 'project'
});
const sql = 'select zipcode, sido, gugun, dong, ri, bunji from zipcode where dong like ?';
conn.query( sql, query.dong + '%', ( err, rows ) => {
if( !err ) {
let result = '<table width="800" border="1"';
rows.forEach( row=> {
result += '<tr>';
//console.log( row.zipcode, row.sido, row.gugun, row.dong, row.ri, row.bunji );
result += '<td>[' + row.zipcode + ' ' + row.sido + ' ' + row.gugun + ' ' + row.dong + ' '
+ row.ri + ' ' + row.bunji + '</td>';
result += '</tr>';
});
result += '</table>';
const html = fs.readFileSync( './public_html/zipsearch_ok.html' );
const tplHtml = eval( '`' + html.toString().replace( /`/g, '\\`' ) + '`' );
res.end( tplHtml );
}
conn.end();
});
});
}
} else {
fs.createReadStream( './public_html/error.html' ).pipe( res );
}
}).listen( 8080, () => {
console.log( '8080 포트에서 요청 대기중 ...' );
});
실행결과
HTTP 웹 프레임워크
- express
https://expressjs.com - koa
- hapi
Express - Node.js web application framework
Fast, unopinionated, minimalist web framework for Node.js $ npm install express --save
expressjs.com
express에 대해 안내서와 api 참조
express
cd
mkdir express1
cd express1/
npm init -y
npm install express
먼저 port 3000번 개방
su - root
cd /usr/lib/firewalld/services/
firewall-cmd --reload
middleware 사용 - 안내서( 미들웨어 작성 )
// express1.js
"use strict";
const express = require( 'express' );
const app = express();
//console.log( app );
// middleware
app.listen( 3000, () => {
console.log( '3000번 포트에서 요청 대기 중 ...' );
});
const myMiddleware = (req, rep, next) => {
console.log( 'MiddelWare' );
next();
}
app.use( myMiddleware );
app.get( '/', (req, rep) => {
rep.send( 'Hello Express' );
});
route 사용( 안내서 - 라우팅 )
// express2.js
"use strict";
const express = require( 'express' );
const app = express();
app.listen( 3000, () => {
console.log( '3000번 포트에서 요청 대기 중 ...' );
});
// Routing
// get
app.get( '/', (req, rep) => { rep.send( '/ get 요청' ); });
app.get( '/users', (req, rep) => { rep.send( '/users 요청' ); });
app.get( '/items', (req, rep) => { rep.send( '/items 요청' ); });
// post
app.post( '/', (req, rep) => { rep.send( '/ post 요청' ); });
route 경로
// express3.js
"use strict";
const express = require( 'express' );
const app = express();
app.listen( 3000, () => {
console.log( '3000번 포트에서 요청 대기 중 ...' );
});
// Routing
app.get( '/ab?cd', function(req, rep) { rep.send( '/ab?cd' ); });
app.get( '/ab+cd', function(req, rep) { rep.send( '/ab+cd' ); });
app.get( '/ab*cd', function(req, rep) { rep.send( '/ab*cd' ); });
app.get( '/ab(cd)?e', function(req, rep) { rep.send( '/ab(cd)?e' ); });
url 경로에서
/ab?cd 는 /acd or /abcd 와 일치
/ab+cd 는 /abcd, /abbcd 및 /abbbcd 등과 일치
/ab*cd 는 /abcd, /abxcd, /abRABDOMcd 및 /ab123cd 등과 일치
/ab(cd)?e 는 /abe 및 /abcde와 일치
route 핸들러
// express4.js
"use strict";
const express = require( 'express' );
const app = express();
app.listen( 3000, () => {
console.log( '3000번 포트에서 요청 대기 중 ...' );
});
app.get( '/', (req, res, next) => {
// Middleware 역할
console.log( 'Hello Middleware' );
next();
}, (req, res) => {
res.send( 'Hello Express' );
});
middleware 역할을 해서
터미널에 출력한뒤 next()로 넘어가서
send 수행
에러 표시 / 에러 처리 / redirect
// express5.js
"use strict";
const express = require( 'express' );
const app = express();
app.listen( 3000, () => {
console.log( '3000번 포트에서 요청 대기 중 ...' );
});
app.get( '/', (req, res) => {
//res.status( 403 ).end();
//res.status( 404 ).send( 'Bad Request' );
//res.redirect( 'https://www.daum.net' );
const html = `<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<boad>
<h1>index.html</h1>
</boad>
</html>`;
res.set( 'Content-Type', 'text/html' );
res.send( html );
});
app.get( '/html', (req, res) => {
console.log( __dirname );
res.sendFile( __dirname + '/index.html' );
});
index.html은 빈파일이지만 html 소스를 보내서 출력함
/html로 접속하면 디렉토리 주소가 터미널에 출력됨
express로 요청 주고 받기
public_html폴더를 만들고 form.html과 form_ok.html을 생성
<!-- form.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>form.html</h1>
<form action="/form_ok" method="get">
data : <input type="text" name="data" />
<input type="submit" value="전송" />
</form>
<br /><hr /><br />
<form action="/form_ok" method="post">
data : <input type="text" name="data" />
<input type="submit" value="전송" />
</form>
</body>
</html>
<!-- form_ok.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>form_ok.html</h1>
</body>
</html>
// server.js
"use strict";
const express = require( 'express' );
const app = express();
app.listen( 3000, () => {
console.log( '3000번 포트에서 요청 대기 중 ...' );
});
app.get( '/', (req, res) => {
//console.log( req.headers );
console.log( req.headers[ 'user-agent' ] );
console.log( req.ip )
res.sendFile( __dirname + '/index.html' );
});
app.get( '/form', (req, res) => {
res.sendFile( __dirname + '/public_html/form.html' );
});
app.get( '/form_ok', (req, res) => {
//console.log( 'get', req.query ); // json 데이터 표시
console.log( 'get', req.query.data );
res.sendFile( __dirname + '/public_html/form_ok.html' );
});
app.use( express.urlencoded( { extended: true } ) ); // post 방식 전송
app.post( '/form_ok', (req, res) => {
//console.log( 'post', req.body );
console.log( 'post', req.body.data );
res.sendFile( __dirname + '/public_html/form_ok.html' );
});
/*
app.all( '/form_ok', (req, res) => {
console.log( 'all' );
res.sendFile( __dirname + '/public_html/form_ok.html' );
});
*/
루트 페이지로 접속하면 index.html 페이지가 출력되고
터미널에 브라우저 정보와 ip주소가 출력됨
/form으로 접속
express로 구구단 만들기
public_html 폴더에 gugudan.html, gugudan_ok.html 생성
<!-- gugudan.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>gugudan.html</h1>
<form action="./gugudan_ok" method="get">
dan : <input type="text" name="dan" />
<input type="submit" value="전송" />
</form>
</body>
</html>
<!-- gugudan_ok.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
<h1>gugudan_ok.html</h1>
<hr /><br />
${ result }
</body>
</html>
express로 우편번호 검색기 만들기