ฉันจะปิดอินสแตนซ์ของ ExpressJS โดยทางโปรแกรมเพื่อทดสอบได้อย่างไร


109

ฉันกำลังพยายามหาวิธีปิดอินสแตนซ์ของ Express โดยพื้นฐานแล้วฉันต้องการการผกผันของการ.listen(port)โทร - ฉันจะทำให้เซิร์ฟเวอร์ Express หยุดฟังปล่อยพอร์ตและปิดอย่างหมดจดได้อย่างไร

ฉันรู้ว่านี่อาจเป็นคำถามแปลก ๆ ดังนั้นนี่คือบริบท อาจมีวิธีอื่นในการเข้าถึงสิ่งนี้และฉันคิดผิด ฉันกำลังพยายามตั้งค่ากรอบการทดสอบสำหรับแอพ socket.io/nodejs ของฉัน มันเป็นแอพหน้าเดียวดังนั้นในสคริปต์การทดสอบของฉัน (ฉันใช้Mochaแต่นั่นไม่สำคัญจริงๆ) ฉันต้องการที่จะสามารถเริ่มต้นเซิร์ฟเวอร์เรียกใช้การทดสอบกับเซิร์ฟเวอร์จากนั้นปิดเซิร์ฟเวอร์ ฉันสามารถหลีกเลี่ยงสิ่งนี้ได้โดยสมมติว่าเซิร์ฟเวอร์เปิดอยู่ก่อนที่การทดสอบจะเริ่มขึ้นหรือโดยการทดสอบอย่างใดอย่างหนึ่งเริ่มเซิร์ฟเวอร์และการทดสอบครั้งต่อ ๆ ไปจะถือว่าขึ้น แต่มันยุ่งมาก ฉันต้องการให้ไฟล์ทดสอบแต่ละไฟล์เริ่มต้นอินสแตนซ์เซิร์ฟเวอร์ด้วยการตั้งค่าที่เหมาะสมแล้วปิดอินสแตนซ์นั้นเมื่อการทดสอบสิ้นสุดลง นั่นหมายความว่าไม่มีการพึ่งพาแปลก ๆ ในการเรียกใช้การทดสอบและทุกอย่างสะอาด นอกจากนี้ยังหมายความว่าฉันสามารถทำการทดสอบการเริ่มต้น / ปิดเครื่องได้

มีคำแนะนำเกี่ยวกับวิธีการทำอย่างไร ฉันคิดเกี่ยวกับการเรียกใช้ข้อยกเว้นด้วยตนเองเพื่อนำมาลง แต่ดูเหมือนจะยุ่ง ฉันขุดผ่านเอกสาร Express และซอร์ส แต่ดูเหมือนจะไม่พบวิธีการใด ๆ ที่จะปิดเซิร์ฟเวอร์ อาจมีบางอย่างใน socket.io สำหรับสิ่งนี้ แต่เนื่องจากเซิร์ฟเวอร์ซ็อกเก็ตเชื่อมต่อกับเซิร์ฟเวอร์ Express ฉันคิดว่าสิ่งนี้จะต้องเกิดขึ้นที่เลเยอร์ด่วน

คำตอบ:


158

สิ่งต่างๆมีการเปลี่ยนแปลงเนื่องจากเซิร์ฟเวอร์ด่วนไม่ได้รับมรดกจากเซิร์ฟเวอร์โหนด http อีกต่อไป โชคดีที่ app.listen ส่งคืนอินสแตนซ์เซิร์ฟเวอร์

var server = app.listen(3000);

// listen for an event
var handler = function() {
  server.close();
};

23
ในกรณีของการทดสอบ Mocha ที่คุณต้องการ ('app') ฉันขยายไปยังวัตถุของแอป: app.server = app.listen (3000); ต่อมาฉันสามารถพูดได้ว่า: var app = require ('./ app'); app.server.close ();
Jack Chi

2
เมื่อทดสอบเซิร์ฟเวอร์โปรดดูที่github.com/visionmedia/supertestซึ่งจะช่วยให้คุณทดสอบโดยไม่เปิดเซิร์ฟเวอร์จริง
Lukas Liesis

ฉันขอแนะนำให้คุณส่งการโทรกลับที่ทำเสร็จแล้วserver.close()หากโทรจากภายในเบ็ด
Ullauri

1
หมายเหตุ: มีความแตกต่างอย่างมากระหว่าง 'app' ซึ่งเป็นอินสแตนซ์ Express Application และค่าที่ส่งคืนของ 'app.listen' ซึ่งเป็นอินสแตนซ์เซิร์ฟเวอร์ HTTP ดั้งเดิมซึ่งมีวิธีการ 'ปิด' @JackChi บอกใบ้ไว้ข้างบนนี้
ajxs

สิ่งนี้ไม่ทำให้เกิดปัญหากับซ็อกเก็ตไคลเอนต์ที่เปิดทิ้งไว้หรือไม่?
Cameron Tacklind

20

ใช้app.close(). ตัวอย่างเต็ม:

var app = require('express').createServer();
app.get('/', function(req, res){
  res.send('hello world');
});
app.get('/quit', function(req,res) {
  res.send('closing..');
  app.close();
});
app.listen(3000);

โทรapp.close()ภายใน callback เมื่อการทดสอบสิ้นสุดลง แต่จำไว้ว่ากระบวนการยังคงทำงานอยู่ (แม้ว่าจะไม่ได้ฟังอีกต่อไป)

หากหลังจากนี้คุณต้องยุติกระบวนการแล้วโทรprocess.exit(0).

ลิงค์:

app.close: http://nodejs.org/docs/latest/api/http.html#server.close (เช่นเดียวกันกับ)

process.exit: http://nodejs.org/docs/latest/api/process.html#process.exit


1
สมบูรณ์แบบในสิ่งที่ฉันกำลังมองหา ฉันเดาว่าฉันไม่พบมันใน Express เพราะพวกเขากำลังขยายเซิร์ฟเวอร์ http ของโหนดหลักซึ่งฉันไม่เข้าใจทั้งหมด ขอบคุณ!
drewww

ขอบคุณ Srijan ที่ช่วยฉันด้วย
Adam Hopkinson

ยังมีอยู่จริงไหม express.createServer ถูกทำเครื่องหมายว่าเลิกใช้งานแล้วและแสดงข้อผิดพลาดว่าแอปไม่ได้รับมรดกจากเซิร์ฟเวอร์ของ http.js อีกต่อไป
Frank Schwieterman

4
สิ่งนี้ไม่ถูกต้องตั้งแต่ express 3
gprasant

4
การเปิดเผย URL เพื่อปิดเซิร์ฟเวอร์เช่นนี้ไม่ใช่ความคิดที่ดี IMHO
shime

2

ฉันได้ตอบ "วิธียุติเซิร์ฟเวอร์ HTTP" หลายครั้งในหลาย ๆ ครั้ง ช่องทางการสนับสนุน น่าเสียดายที่ฉันไม่สามารถแนะนำไลบรารีใด ๆ ที่มีอยู่ได้เนื่องจากไม่มีในทางใดทางหนึ่ง ฉันได้รวบรวมแพ็คเกจที่ (ฉันเชื่อว่า) กำลังจัดการทุกกรณีที่คาดว่าจะมีการยุติเซิร์ฟเวอร์ HTTP อย่างสง่างาม

https://github.com/gajus/http-terminator

ประโยชน์หลักของhttp-terminatorคือ:

  • มันไม่ลิงแพทช์ Node.js API
  • มันทำลายซ็อกเก็ตทั้งหมดทันทีโดยไม่ต้องแนบคำขอ HTTP
  • ช่วยให้การหมดเวลาอย่างสง่างามในการซ็อกเก็ตที่มีคำขอ HTTP อย่างต่อเนื่อง
  • จัดการการเชื่อมต่อ HTTPS อย่างเหมาะสม
  • มันแจ้งการเชื่อมต่อโดยใช้ keep-alive ว่าเซิร์ฟเวอร์กำลังปิดโดยตั้งค่าการเชื่อมต่อ: ปิดส่วนหัว
  • มันไม่ได้ยุติกระบวนการ Node.js

การใช้งานกับ Express.js:

import express from 'express';
import {
  createHttpTerminator,
} from 'http-terminator';

const app = express();

const server = app.listen();

const httpTerminator = createHttpTerminator({
  server,
});

await httpTerminator.terminate();


-1

คุณสามารถทำได้อย่างง่ายดายโดยเขียนสคริปต์ทุบตีเพื่อเริ่มเซิร์ฟเวอร์เรียกใช้การทดสอบและหยุดเซิร์ฟเวอร์ สิ่งนี้มีข้อดีคือช่วยให้คุณสามารถใช้นามแฝงของสคริปต์นั้นเพื่อเรียกใช้การทดสอบทั้งหมดของคุณได้อย่างรวดเร็วและง่ายดาย

ฉันใช้สคริปต์ดังกล่าวสำหรับกระบวนการปรับใช้อย่างต่อเนื่องทั้งหมดของฉัน คุณควรดูDead Simple Git Workflow ของ Jon Rohanเพื่อรับข้อมูลเชิงลึกเกี่ยวกับเรื่องนี้


2
วิธีนี้ใช้ได้ แต่ฉันต้องการโซลูชันที่ไม่ต้องทุบตีถ้าเป็นไปได้ อาจจะเป็นการตั้งค่าที่งี่เง่า แต่ฉันต้องการเริ่ม / หยุดเซิร์ฟเวอร์จากบริบทการทดสอบเพราะทำให้ง่ายต่อการเขียนการทดสอบการกำหนดค่าเซิร์ฟเวอร์เฉพาะ + การทดสอบการเริ่มต้น / ปิดระบบ นอกจากนี้ยังไม่แนะนำทิศทางของการต้องเรียกใช้การทดสอบที่เกี่ยวข้องกับเซิร์ฟเวอร์ผ่านสคริปต์แยกต่างหาก
drewww

เหตุใดคุณจึงเขียนแบบทดสอบเฉพาะสภาพแวดล้อม บางทีฉันอาจจะผิด แต่สิ่งนี้ทำให้ฉันรู้สึกแย่ ฉันจะพยายามรักษาสภาพแวดล้อมโดยไม่เชื่อเรื่องพระเจ้าด้วยการทดสอบของคุณเนื่องจากคุณต้องการให้การทดสอบของคุณทำงานร่วมกับทีมของคุณโดยไม่คำนึงถึงสภาพแวดล้อมการพัฒนาของพวกเขา
Josh Smith

ฉันไม่ได้ทำอะไรที่เฉพาะเจาะจงด้านสิ่งแวดล้อมที่นี่ฉันไม่คิดว่า จะมีตัวเลือกการเริ่มต้นที่แตกต่างกันสำหรับเซิร์ฟเวอร์ (เช่นการอ่านตัวเลือกการกำหนดค่าจากไฟล์สถานะการโหลดจากที่เก็บข้อมูล ฯลฯ ) ซึ่งจะเป็นการดีที่จะทดสอบในกรอบเดียวกันกับที่ฉันทดสอบทุกอย่าง ฉันต้องการทดสอบเช่นปิดเซิร์ฟเวอร์นำกลับมาอีกครั้งและตรวจสอบให้แน่ใจว่าไม่สูญเสียสถานะในกระบวนการ มันง่ายกว่าถ้าฉันสามารถทำได้โดยทางโปรแกรมจากโหนดมากกว่าการทดสอบโค้ดใน bash ด้วย
drewww

คุณจะไม่วางรหัสทดสอบของคุณใน bash เอง คุณเพียงแค่เริ่มต้นเซิร์ฟเวอร์และเรียกใช้การทดสอบจากสคริปต์เช่นเดียวกับที่คุณทำเองในบรรทัดคำสั่ง ไม่มีเวทมนตร์พิเศษที่แท้จริงที่นั่น
Josh Smith
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.