클라이언트가 보낸 HTTP 요청 정보를 표시하는 웹 페이지 제공

Aug 21 2020

Node와 JavaScript로 웹 서버 프로그래밍을 배우기 위해 저는 한 가지만 수행하는 간단한 웹 서버를 구현하기로 결정했습니다.

  • HTTP 요청의 데이터를 HTML 테이블로 표시합니다.

표시 할 실제 데이터는 임의적입니다. 이 예에서는 메소드, URL 및 http 버전과 함께 헤더의 내용을 표시합니다.

다음은 작업 솔루션입니다.

const http = require('http');

const port = 3344;

const htmlCSS = `
  <style>
    body {
      font-family: sans-serif;
    }

    td {
      border: 1px solid black;
      padding: 0.5rem;
    }

    table {
      margin: 0 auto;
    }
  </style>
`;

const server = http.createServer((req, res) => {
  const {
    headers,
    method,
    url
  } = req;

  console.log(`\n${headers['user-agent']}\n${method}\n${url}`); console.log(new Date()); console.log(); writeResponse(req, res); }); server.listen(port); function writeResponse(req, res) { res.statusCode = 200; res.setHeader('Content-Type', 'text/html'); writeBody(req, res); res.end(); } function writeBody(req, res) { const htmlTitle = '<title>Your Request Is</title>'; const htmlEncode = '<meta charset="UTF-8">'; const htmlHead = `<head>${htmlTitle}${htmlCSS}${htmlEncode}</head>`;
  const htmlTop = `<html lang="en">${htmlHead}<body>`; const htmlBot = '</body></html>'; res.write(htmlTop); writeTable(req, res); res.write(htmlBot); } function writeTable(req, res) { const htmlTableTop = '<table><tbody>'; const htmlTableBot = '</tbody></table>'; res.write(htmlTableTop); writeAllRows(req, res); res.write(htmlTableBot); } function writeAllRows(req, res) { const { httpVersion, httpVersionMinor, httpVersionMajor, headers, method, url } = req; for (const key in headers) { writeRow(res, key, headers[key]); } writeRow(res, 'method', method); writeRow(res, 'url', url); writeRow(res, 'httpVersion', httpVersion); writeRow(res, 'httpVersionMinor', httpVersionMinor); writeRow(res, 'httpVersionMajor', httpVersionMajor); } function writeRow(res, key, val) { const entry = `<tr><td>${key}</td><td>${val}</td></tr>`;
  res.write(entry);
}

몇 가지 특별한 질문이 있지만 모든 종류의 피드백을 기다리고 있습니다! 따라서 개선 할 수있는 사항이 있으면 모든 의견을 보내 주시면 감사하겠습니다!

  • 이 작업을 더 쉽게하기 위해 다른 모듈을 사용할 수 있습니까?
  • 이 간단한 작업의 경우 HTML과 CSS를 별도의 파일로 사용하는 것이 가치가 있습니까?
  • HTML과 CSS는 일반적으로 JS 파일 (편집, 추가 등) 내에서 어떻게 처리됩니까?
  • HTML 및 CSS 구성을 얼마나 잘 처리하고 있습니까?
  • 더 간결하게 할 수 있습니까?
  • 어떤 식 으로든이를 개선하기 위해 다르게 무엇을 하시겠습니까?

답변

5 ManuelSpigolon Aug 21 2020 at 20:07

이 작업을 더 쉽게하기 위해 다른 모듈을 사용할 수 있습니까?

fastify 또는 express 와 같은 일부 웹 프레임 워크를 사용할 수 있습니다 . 이것은 코드를 많이 완화시킬 것입니다.

이 간단한 작업의 경우 HTML과 CSS를 별도의 파일로 사용하는 것이 가치가 있습니까?

프로젝트가 커진다고 가정하면 별도의 파일에서 일부 "정적 텍스트"를 이동하는 것이 좋습니다.

HTML과 CSS는 일반적으로 JS 파일 (편집, 추가 등) 내에서 어떻게 처리됩니까?

손으로 서버 측 렌더링 (SSR)을 만들었습니다. 모든 문자열을 수동으로 관리하는 것이 어렵고 일부 스크립트 삽입에도 위험 할 수 있으므로 일부 fremework를 vue 또는 handlebarsjs 또는 기타 와 같은 다른 템플릿 시스템 으로 사용할 수 있습니다. 여기 목록이 있습니다.

HTML 및 CSS 구성을 얼마나 잘 처리하고 있습니까?

해당 값을 처리하기 시작하면 다음과 같은 링크에 대한 보안 문제가있을 수 있습니다.

http://localhost:3000/?user=%3Cimg%20src=%27aaa%27%20onerror=alert(1)%3E

프레임 워크는 일반적으로 이러한 경우로부터 사용자를 보호합니다.

이 코드 :

  const htmlTitle = '<title>Your Request Is</title>'
  const htmlEncode = '<meta charset="UTF-8">'
  const htmlHead = `<head>${htmlTitle}${htmlCSS}${htmlEncode}</head>` const htmlTop = `<html lang="en">${htmlHead}<body>`

매번 동일한 출력 문자열을 생성하므로 모든 요청 대신 한 번 수행 할 수 있습니다. 이렇게하면 처리량이 높은 사이트에 대한 nodejs 가비지 수집기에 스트레스가 덜합니다.

더 간결하게 할 수 있습니까?

일부 ObjectArray함수를 사용하여 코드를 적게 작성할 수 있습니다.

function stringTemplates (request) {
  return `<html lang="en">
<head>
<title>Your Request Is</title>
</head>
<body>
<table><tbody>
${Object.entries(request.headers).map(processLine).join('')} ${['httpVersion', 'httpVersionMinor', 'httpVersionMajor', 'method', 'url'].map(prop => processLine([prop, request[prop]])).join('')}
</tbody></table>
</body>
</html>
`
}

function processLine ([header, value]) {
  return `<tr><td>${header}</td><td>${value}</td></tr>`
}

어떤 식 으로든이를 개선하기 위해 다르게 무엇을 하시겠습니까?

이것은 GET 만 보여 주지만 HTTP 표준을 배우기 위해서는 다음과 같이 표시하는 것이 유용 할 것입니다.

  • 쿼리 매개 변수
  • 양식 매개 변수 (다른 인코딩 사용)
2 SᴀᴍOnᴇᴌᴀ Aug 21 2020 at 22:27

어떤 식 으로든이를 개선하기 위해 다르게 무엇을 하시겠습니까?

얼마나 비싼지는 모르겠지만 res.write()호출 횟수를 최소화하는 것을 목표로하고 있습니다. 이를 위해 행을 생성하는 함수가 문자열을 반환하고 각 행의 문자열을 배열로 수집 한 다음을 사용하여 Array.prototype.join()단일 호출에 전달하는 데 사용하는 배열을 조인합니다 res.write().


이 코드는 const변수 범위를 제한하고 우발적 인 재 할당을 방지 하는 데 유용 합니다. 런타임 중에 절대 변경되지 않아야하는 상수 값에도 사용할 수 있습니다.

상수는 대문자 또는 소문자로 선언 할 수 있지만 일반적인 규칙은 모두 대문자를 사용하는 것입니다. 1

이름은 같은 htmlCSSHTML_CSS, port수 있었다 PORT. 이렇게하면 코드를 읽는 사람은 해당 값을 변경해서는 안된다는 것을 알 수 있습니다. 곰 염두에로 선언 된 객체 / 배열이 있음을 const의 호출에 싸여 않는 불변하지 않습니다 Object.freeze().