Comments (5)
Currently there is indeed no way of closing the listener. It would be a good idea to revamp the HTTP module with more careful design (and possibly emulating part of implementation from Go) (a few contributors have expressed interest on this)
from deno_std.
Yep, seems like this isn't possible right now. I was looking for a way to implement a server.close() equivalent in pogo, to gracefully stop accepting requests and allow the process to exit with a status code of zero (success). This is needed for production deployments, where killing a process from the outside can cause all kinds of problems.
from deno_std.
For people who want this feature immediately, it is possible to add server.close
feature given current http.ts
structure. Basically you want to add something so that you can call and stops
Lines 60 to 69 in bef7ba1
(this piece of code immediately tries to wait for a next
accept
when the previous one is handled)and also breaks from
Lines 74 to 85 in bef7ba1
(This is for sure not an elegant structure. I hope someone could take some time to improve this while still keeping the capability of doing async iterator for request handling.)
from deno_std.
Maybe I could do something along the lines of:
class App {
async handleRequest(request) {
// ... do stuff with request ...
}
close() {
this._shouldClose = true;
}
async start() {
const server = http.serve('localhost:1234');
for await (const request of server) {
await this.handleRequest(request);
if (this._shouldClose) {
break;
}
}
}
}
But I haven't tested it. And I think that would wait for a request to come in before closing, which seems bad.
from deno_std.
I'm testing a hack to support closing the server, preferably something with very few and simple changes.
For example this is a way you could run the server and handle it closing:
const generatorStopper = {stop: null}
const requestGenerator = http.serve(this.address, generatorStopper)
for await (const req of requestGenerator) {
if (req === false) {
log('Server has closed')
break
}
// else handle the request
}
Where this would be called to stop it:
generatorStopper.stop()
And how the serve generator function could implement it (tested and works). I'm no TypeScript programmer, so please excuse my dirty JavaScript... :P
export async function* serve(addr: string, generatorStopper) {
const listener = listen("tcp", addr);
const env: ServeEnv = {
reqQueue: [], // in case multiple promises are ready
serveDeferred: deferred()
};
// Routine that keeps calling accept
let handleConn = (_conn: Conn) => {};
let scheduleAccept = () => {};
const acceptRoutine = () => {
scheduleAccept = () => {
listener.accept().then(handleConn).catch(()=>{/*ignore*/});
};
handleConn = (conn: Conn) => {
serveConn(env, conn); // don't block
scheduleAccept(); // schedule next accept
};
scheduleAccept();
};
acceptRoutine();
if (typeof generatorStopper == 'object' && 'stop' in generatorStopper) {
generatorStopper.stop = (() => {
env.serveDeferred.resolve(false);
});
}
// Loop hack to allow yield (yield won't work in callbacks)
while (true) {
if (await env.serveDeferred.promise === false) {
break
}
env.serveDeferred = deferred(); // use a new deferred
let queueToProcess = env.reqQueue;
env.reqQueue = [];
for (const result of queueToProcess) {
yield result;
// Continue read more from conn when user is done with the current req
// Moving this here makes it easier to manage
serveConn(env, result.conn, result.r);
}
}
listener.close();
yield false;
}
Of course I modified a few other places in the code to support the new "false" type. E.g:
interface Deferred {
promise: Promise<{}>;
resolve: (arg) => void;
reject: () => void;
}
And the listenAndServe
function needs to be modified also, or just commented away.
If doing something like this then we need a way to handle "Uncaught Other: Listener has been closed". I have not tried to solve everything yet... I've just spent a few minutes at this! And if we need to connect to our own server for the socket.accept() function to stop holding, then that's an easy hack to fix that...
EDIT: Fixed the uncaught exception.
All I'm saying is that there are solutions to implement a way to close the server and it is not hard to do. But since I'm no TypeScript programmer I'm not really going to contribute with any pull requests any time soon, I don't have the energy/health to get involved in this yet.
EDIT: Added this text:
If you want to try these changes out then just create a "httpServer.js" file in your project directory and copy the contents of "https://deno.land/x/http/server.ts" into it. With these changes at the top (so your local file can fully replace the one at the server):
import { BufReader, BufState, BufWriter } from "https://deno.land/x/io/bufio.ts";
import { TextProtoReader } from "https://deno.land/x/textproto/mod.ts";
import { STATUS_TEXT } from "https://deno.land/x/http/http_status.ts";
import { assert } from "https://deno.land/x/testing/asserts.ts";
Add rest of changes and then import that file instead in your project:
import * as http from "httpServer.ts"
from deno_std.
Related Issues (20)
- The web doc of `[email protected]/path` downloads the .ts files instead of showing documentation HOT 2
- web doc for `[email protected]/collections` missing HOT 3
- feature: add synchronization primitives ? HOT 1
- proposal: `ARCHITECTURE.md`
- Proposal: Migrate to JSR-oriented codebase HOT 5
- csv - parse takes undefined opt HOT 4
- csv - stringify with no options should not output an empty blank line before the data
- suggestion: mock `performance.now()` in `FakeTime` HOT 8
- [Suggestion] A module that includes BigInt utilities
- suggestion: mention deprecated module before removal HOT 1
- 0.222.0 introduced breaking std/log behavior HOT 5
- suggestion: simplify `load()` from `std/dotenv` HOT 5
- suggestion: add hexdump format for `ArrayBuffer` HOT 11
- suggestion: add guide on how to use the Standard Library in the browser HOT 1
- Change publish workflow to use canary HOT 1
- todo: split `toml/test.ts` into separate files HOT 2
- [http/file_server] Show local network IP HOT 4
- The Road to Stabilizing the Standard Library HOT 2
- todo: create test for `std/http/file-server` HOT 1
- `csv/parse_test.ts` has type errors, but they are not caught in CI HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from deno_std.