oakserver / oak Goto Github PK
View Code? Open in Web Editor NEWA middleware framework for handling HTTP with Deno, Node, Bun and Cloudflare Workers 🐿️ 🦕
Home Page: https://oakserver.org
License: MIT License
A middleware framework for handling HTTP with Deno, Node, Bun and Cloudflare Workers 🐿️ 🦕
Home Page: https://oakserver.org
License: MIT License
I started a server with the following code.
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
async function server() {
const app = new Application();
const router = new Router();
router.post("/json", async ctx => {
ctx.response.body = "test";
});
app.use(router.routes());
await app.listen(`0.0.0.0:5000`);
}
server();
But when I submit requests usingPOST
and application/json
. The first time I get the right response, however, all subsequent requests will get 404 errors
However, when I use curl access, it seems normal. It only happens on the browser and postman. I guess it's related to the reuse of connections.
Hi Everyone,
I am try Oak middleware as as example below:
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use((ctx) => {
ctx.response.body = "Hello world!";
});
await app.listen("127.0.0.1:8000");
I already install typescript as global npm install -g typescript
, and run Deno on terminal with deno --allow-net .\oak.ts
, my operating system Win 10 is latest version update, and i also try running as Administrator or another user on terminal and with same Error output, anyone can point some best a away..?, thanks in advance
Error appear as below:
Compile file:///D:/deno-sample/oak.ts
error TS2322: Type '(_: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'.
Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
► https://deno.land/[email protected]/http/_io.ts:10:5
10 read(_: Uint8Array): Promise<number | null> {
~~~~
error TS2322: Type '(buf: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'. Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
► https://deno.land/[email protected]/http/_io.ts:35:12
35 return { read };
~~~~
error TS2322: Type '(buf: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'. Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
► https://deno.land/[email protected]/http/_io.ts:113:12
113 return { read };
~~~~
error TS2339: Property 'iter' does not exist on type 'typeof Deno'.
► https://deno.land/[email protected]/http/_io.ts:167:34
167 for await (const chunk of Deno.iter(r)) {
~~~~
error TS2345: Argument of type 'Reader' is not assignable to parameter of type 'Writer'.
Property 'write' is missing in type 'Reader' but required in type 'Writer'.
► https://deno.land/[email protected]/http/_io.ts:265:31
265 const n = await Deno.copy(r.body, writer);
~~~~~~
'write' is declared here.
► $asset$/lib.deno.ns.d.ts:463:5
463 write(p: Uint8Array): Promise<number>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2339: Property 'listenTls' does not exist on type 'typeof Deno'.
► https://deno.land/[email protected]/http/server.ts:16:17
16 const { listen, listenTls } = Deno;
~~~~~~~~~
error TS2694: Namespace 'Deno' has no exported member 'ListenTlsOptions'.
► https://deno.land/[email protected]/http/server.ts:289:38
289 export type HTTPSOptions = Omit<Deno.ListenTlsOptions, "transport">;
~~~~~~~~~~~~~~~~
error TS2694: Namespace 'Deno' has no exported member 'ListenTlsOptions'.
► https://deno.land/[email protected]/http/server.ts:309:26
309 const tlsOptions: Deno.ListenTlsOptions = {
~~~~~~~~~~~~~~~~
error TS2694: Namespace 'Deno' has no exported member 'WriterSync'.
► https://deno.land/[email protected]/io/bufio.ts:8:24
8 type WriterSync = Deno.WriterSync;
~~~~~~~~~~
error TS2469: The '>=' operator cannot be applied to type 'symbol'.
► https://deno.land/[email protected]/io/bufio.ts:90:14
90 assert(rr >= 0, "negative read");
~~
error TS2365: Operator '+=' cannot be applied to types 'number' and 'number | unique symbol'.
► https://deno.land/[email protected]/io/bufio.ts:91:7
91 this.w += rr;
~~~~~~~~~~~~
error TS2469: The '>' operator cannot be applied to type 'symbol'.
► https://deno.land/[email protected]/io/bufio.ts:92:11
92 if (rr > 0) {
~~
error TS2416: Property 'read' in type 'BufReader' is not assignable to the same property in base type 'Reader'.
Type '(p: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'.
Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
Type 'number | null' is not assignable to type 'number | unique symbol'.
Type 'null' is not assignable to type 'number | unique symbol'.
► https://deno.land/[email protected]/io/bufio.ts:123:9
123 async read(p: Uint8Array): Promise<number | null> {
~~~~
error TS2469: The '>=' operator cannot be applied to type 'symbol'.
► https://deno.land/[email protected]/io/bufio.ts:133:16
133 assert(nread >= 0, "negative read");
~~~~~
error TS2322: Type 'number | unique symbol' is not assignable to type 'number | null'.
Type 'unique symbol' is not assignable to type 'number | null'.
► https://deno.land/[email protected]/io/bufio.ts:138:9
138 return rr;
~~~~~~~~~~
error TS2322: Type 'number | unique symbol' is not assignable to type 'number | null'.
Type 'unique symbol' is not assignable to type 'number | null'.
► https://deno.land/[email protected]/io/bufio.ts:145:7
145 rr = await this.rd.read(this.buf);
~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/_constants.ts:51:19
51 const isWindows = build.os == "windows";
~~~~~~~~~~~~~~~~~~~~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/_globrex.ts:5:15
5 const isWin = Deno.build.os === "windows";
~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/mod.ts:7:19
7 const isWindows = Deno.build.os == "windows";
~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2345: Argument of type 'string | URL' is not assignable to parameter of type 'string'.
Type 'URL' is not assignable to type 'string'.
► https://deno.land/[email protected]/path/posix.ts:433:18
433 return new URL(url).pathname;
~~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/separator.ts:2:19
2 const isWindows = Deno.build.os == "windows";
~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2339: Property 'get' does not exist on type '{ (): { [index: string]: string; }; (key: string): string | undefined; }'.
► https://deno.land/[email protected]/path/win32.ts:42:18
42 path = env.get(`=${resolvedDevice}`) || cwd();
~~~
error TS2345: Argument of type 'string | URL' is not assignable to parameter of type 'string'.
Type 'URL' is not assignable to type 'string'.
► https://deno.land/[email protected]/path/win32.ts:911:18
911 return new URL(url).pathname
~~~
error TS2304: Cannot find name 'AbortSignal'.
► https://deno.land/x/oak/application.ts:18:12
18 signal?: AbortSignal;
~~~~~~~~~~~
error TS2304: Cannot find name 'AbortSignal'.
► https://deno.land/x/oak/application.ts:27:12
27 signal?: AbortSignal;
~~~~~~~~~~~
error TS2304: Cannot find name 'ErrorEventInit'.
► https://deno.land/x/oak/application.ts:45:11
45 extends ErrorEventInit {
~~~~~~~~~~~~~~
error TS2304: Cannot find name 'ErrorEvent'.
► https://deno.land/x/oak/application.ts:78:61
78 export class ApplicationErrorEvent<S extends State> extends ErrorEvent {
~~~~~~~~~~
error TS2345: Argument of type '{ context: Context<S>; message: any; error: any; }' is not assignable to parameter of type 'ApplicationErrorEventInit<S>'.
Object literal may only specify known properties, and 'message' does not exist in type 'ApplicationErrorEventInit<S>'.
► https://deno.land/x/oak/application.ts:153:53
153 new ApplicationErrorEvent("error", { context, message, error }),
~~~~~~~
error TS2416: Property 'addEventListener' in type 'Application<S>' is not assignable to the same property in base type 'EventTarget'.
Type '(type: "error", listener: ApplicationErrorEventListener<S> | ApplicationErrorEventListenerObject<S> | null, options?: any) => void' is not assignable to type '(type: string, callback: EventListener | EventListenerObject | null, options?: boolean | AddEventListenerOptions | undefined) => void'.
Types of parameters 'listener' and 'callback' are incompatible.
Type 'EventListener | EventListenerObject | null' is not assignable to type 'ApplicationErrorEventListener<S> | ApplicationErrorEventListenerObject<S> | null'.
Type 'EventListener' is not assignable to type 'ApplicationErrorEventListener<S> | ApplicationErrorEventListenerObject<S> | null'.
Type 'EventListener' is not assignable to type 'ApplicationErrorEventListener<S>'.
Types of parameters 'evt' and 'evt' are incompatible.
Type 'ApplicationErrorEvent<S>' is missing the following properties from type 'Event': type, target, currentTarget, composedPath,
and 17 more.
► https://deno.land/x/oak/application.ts:202:3
202 addEventListener(
~~~~~~~~~~~~~~~~
error TS2304: Cannot find name 'AddEventListenerOptions'.
► https://deno.land/x/oak/application.ts:205:25
205 options?: boolean | AddEventListenerOptions,
~~~~~~~~~~~~~~~~~~~~~~~
error TS2416: Property 'addEventListener' in type 'Application<S>' is not assignable to the same property in base type 'EventTarget'.
Type '(type: "error", listener: ApplicationErrorEventListener<S> | ApplicationErrorEventListenerObject<S> | null, options?: any) => void' is not assignable to type '(type: string, callback: EventListener | EventListenerObject | null, options?: boolean | AddEventListenerOptions | undefined) => void'.
► https://deno.land/x/oak/application.ts:207:3
207 addEventListener(
~~~~~~~~~~~~~~~~
error TS2304: Cannot find name 'EventListenerOrEventListenerObject'.
► https://deno.land/x/oak/application.ts:209:15
209 listener: EventListenerOrEventListenerObject | null,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2304: Cannot find name 'AddEventListenerOptions'.
► https://deno.land/x/oak/application.ts:210:25
210 options?: boolean | AddEventListenerOptions,
~~~~~~~~~~~~~~~~~~~~~~~
error TS2345: Argument of type '{ message: string; error: any; }' is not assignable to parameter of type 'ApplicationErrorEventInit<Record<string | number | symbol, any>>'.
Object literal may only specify known properties, and 'message' does not exist in type 'ApplicationErrorEventInit<Record<string | number | symbol, any>>'.
► https://deno.land/x/oak/application.ts:254:46
254 new ApplicationErrorEvent("error", { message, error }),
~~~~~~~
error TS2322: Type '() => boolean' is not assignable to type 'boolean'.
► https://deno.land/x/oak/send.ts:62:12
62 return (await Deno.stat(path)).isFile;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Did you mean to call this expression?
► https://deno.land/x/oak/send.ts:62:12
62 return (await Deno.stat(path)).isFile;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
► https://deno.land/x/oak/send.ts:135:9
135 if (stats.isDirectory) {
~~~~~~~~~~~~~~~~~
error TS2339: Property 'mtime' does not exist on type 'FileInfo'.
► https://deno.land/x/oak/send.ts:151:55
151 if (!response.headers.has("Last-Modified") && stats.mtime) {
~~~~~
error TS2339: Property 'mtime' does not exist on type 'FileInfo'.
► https://deno.land/x/oak/send.ts:152:49
152 response.headers.set("Last-Modified", stats.mtime.toUTCString());
~~~~~
Found 38 errors.
I ask this question because in the readme I only see c.params
and c.request.body()
...
For now how can I retrieve query params?
Thanks.
The object Deno changed. please use Deno.errors.NotFound instead of Deno.NotFound
error TS2339: Property 'ErrorKind' does not exist on type 'typeof Deno'.
► https://deno.land/x/oak/send.ts:149:29
149 if (err.kind === Deno.ErrorKind.NotFound) {
~~~~~~~~~
Per denoland/deno#5176, the v1.0.0-rc1
tag on std
was a mistake and one should use . v0.42.0
(with the same Deno version)v0.50.0
is now up.
TIA
The example for ErrorHandling in the readme does not work, stating that Type 'Status.NotFound' is not comparable to type 'ErrorStatus'.
This is the said part of the readme
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
if (isHttpError(err)) {
switch (err.status) {
case Status.NotFound:
// handle NotFound
break;
default:
// handle other statuses
}
} else {
// rethrow if you can't handle the error
throw err;
}
}
});
The fix that I could come up with is not pretty and is to cast err.status as Status
but that is only possible by casting into unknown
first and then into Status
switch (err.status as unknown as Status) {
Am I missing something?
How can I get a list of all the routes that my router has available?
Guiding myself from the self question in Koa something like this can be done:
router.get('/', async (context: RouterContext) => {
context.response.body = "This is a response";
});
router.stack.map(i => i.path);
Hi,
I am new to deno
and oak
.
The below code doesnt work for post
method but WORKS for get
.
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
const router = new Router();
router
.post("/", context => {
context.response.body = "Hello world Johnson!";
});
const app = new Application();
app.use(router.routes());
app.use(router.allowedMethods());
await app.listen("127.0.0.1:8000");
Any thoughts on this? Thanks in advance.
First and foremost: keep up the good work, i like where this project is going (:
I tried to implement an fs.watch logic that restarts oak on file change. For this I added the AbortController as mentioned in the README and I added controller.abort()
to my fs.watch. Unfortunately neither the promise from app.listen was ever resolved, nor was the underlying server closed - it also seems like server.close()
is not called in https://github.com/oakserver/oak/blob/master/application.ts#L226
Do I misunderstand the idea behind the AbortController? Or is this just not fully implemented?
I tried to send HTTP GET
request with Transfer-encoding: chunked
in the request header such as following command then.
$ curl "http://localhost:8000" -H "Transfer-encoding: chunked"
Then http server process faced UnexpectedEOFError
.
error: Uncaught UnexpectedEOFError: Unexpected EOF
► io.ts:66:34
66 if (line === Deno.EOF) throw new UnexpectedEOFError();
^
at UnexpectedEOFError (bufio.ts:28:5)
at read (io.ts:66:34)
server.ts is following.
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use(ctx => {
ctx.response.body = "Hello World!";
});
await app.listen({ port: 8000 });
It will be nice to have GraphQL middleware. I'd like to help with it.
Trying to serve static files using this code snippet in the README.md yield the following error.
app.use(async (context) => { await send(context, context.request.path, { root: "./static", index: "index.html", }); });
Error.
error TS2339: Property 'path' does not exist on type 'Request'. await send(context, context.request.path, {
There doesn't seem to be a way to handle BrokenPipe
errors thrown in std/http/server.ts
for individual requests from oak without modifying the Application
class. The error occurs if the HTTP client closes the connection prematurely.
Here is an example.
import { Application, Router } from "https://deno.land/x/oak/mod.ts";
console.log("Starting...");
const router = new Router();
const veryLong = "foo bar baz qux ".repeat(1000000);
router.get("/demo", async ctx => {
ctx.response.type = "text/html; charset=utf-8";
ctx.response.body = `<h1>Hello!</h1>\n${veryLong}`;
});
const app = new Application();
app
.use(router.routes())
.use(router.allowedMethods())
.listen("localhost:8080");
Save the code above as demo.ts
and run the following shell commands to reproduce the error.
> deno --version
deno 0.31.0
v8 8.1.108
typescript 3.7.2
> deno --allow-net demo.ts &
> Compile file:///home/dbohdan/demo.ts
Starting...
> curl http://localhost:8080/demo & sleep 0.1; killall curl
> error: Uncaught BrokenPipe: Broken pipe (os error 32)
► $deno$/dispatch_minimal.ts:59:11
at DenoError ($deno$/errors.ts:20:5)
at unwrapResponse ($deno$/dispatch_minimal.ts:59:11)
at sendAsyncMinimal ($deno$/dispatch_minimal.ts:102:10)
fish: Job 2, “curl http://localhost:8080/demo…” terminated by signal SIGTERM (Polite quit request)
Job 1, 'deno --allow-net demo.ts &' has ended
Hello, I'm trying to use error handler, however I'm not able to use it
Can anyone help?
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use((ctx) => {
ctx.throw(500);// Uncaught ReferenceError: ErrorEvent is not defined
});
app.addEventListener("error", (evt) => {
console.log(evt.error);
});
await app.listen({ port: 8000 });
Since this project followed koa's design, it has the same problem on types. Here I have a proposal to bring better type support for middleware.
The problem is that you cannot extend Application's type parameter when applying middlewares(which attach extra properties to ctx.state
) on it. For example:
const app = new Application()
app.use(ctx => {
ctx.state.username = 'foo'
}).use(ctx => {
// not type safe for username
ctx.state.username
})
My idea is we can change the prototype of use
like this:
class Application<S>{
use<NS extends {} = S>(middleware: Middleware<NS, Context<NS>>): Application<NS extends S ? NS : (S & NS)>
}
So we can happily write middleware with type checking:
// when need to extend context type, declare only what you want to attach
app.use((ctx: Context<{ name: string }>) => {
ctx.state.name = 'foo'
// I'm not including next here for simplification
})
// extend again
.use((ctx: Context<{ id: string }>) => {
ctx.state.id = 'id'
})
// context type is by default according to last middleware
.use((ctx) => {
// ctx has a default type
ctx.state.id = 'id'
ctx.state.name = 'name'
})
It's not hard to do so if we don't support applying multiple middleware by one use
call(which should be a rare use case).
And it's a little complicated for Router
, we also want Router
to have same context type as Application
, so the Router
instance must be created by a Application
instance, so its type parameter can be inherited.
Application<S> {
createRouter(): Router<S>
}
If you're good with this, I'll be working on it and send a pull request. Or please reply if have any comments.
I hope some easy cookie handler could be implemented just like koa did.
app.use(async (ctx) => {
ctx.cookies.get('key'); // => "value" | undefined
ctx.cookies.set('key', 'value', { httpOnly: true });
// => set `Set-Cookie` header automatically
})
Need to update CI deno version
Hello!
So I've been trying to use oak to tinker arround and found either a bug or I'm using it in an incorrect way.
I have the following router :
const TodoRouter = new Router({
prefix: '/api/todo'
});
TodoRouter.get('/' , async (ctx) => {
console.log('api')
ctx.response.body = "Hello world"
} )
What I expected : doing a Get request to localhost:port/api/todo would return "Hello World"
What happened : Doing a Get Request to localhost:port/api/todo return nothing
So my Question is, when using a Router without a Prefix, the '/' route, work for either localhost:port and localhost:port/ so I would assume that with a prefix works the same, with that in mind is this the correct behaviour or a bug?
Thanks in advance
Should be content-type
:
https://github.com/kitsonk/oak/blob/89c16553315ad7884023f9d874433e149105b892/response.ts#L22
Hey @kitsonk !
Currently I'm using git commit hash to fix to a version (ex: Deno v0.42, 1.0.0 rc2, etc) so I can use it in my project, but it would be way better to have a tag to fix to.
Implement something like express' bodyParser
middleware
Want to know if MySQL has a driver
Or is it possible to support it?
Hi team,
great work! I am getting started with oak these days and looking for some materials, like API documentation. Is there any official API documentation available?
All the best,
Florian
Is there currently support for redirects from the server side? Can't find it anywhere in the code or documentation.
Hey, guys, how are you?
I'm starting my studies with the deno and I came across the following message: what could be wrong?
peidrao in deno on master [?] took 11s
❯ sudo deno helloDenos.ts
Compile file:///home/peidrao/deno/helloDenos.ts
error: Uncaught PermissionDenied: network access to "127.0.0.1:3000", run again with the --allow-net flag
► $deno$/ops/dispatch_json.ts:43:11
at PermissionDenied ($deno$/errors.ts:81:5)
at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
at sendSync ($deno$/ops/dispatch_json.ts:72:10)
at listen ($deno$/ops/net.ts:50:10)
at listen ($deno$/net.ts:168:18)
at serve (server.ts:251:20)
at listen (application.ts:29:25)
at helloDenos.ts:8:5
Deno's current Response
interface allows Reader
as the body type.
/**
* Interface of HTTP server response.
* If body is a Reader, response would be chunked.
* If body is a string, it would be UTF-8 encoded by default.
*/
export interface Response {
status?: number;
headers?: Headers;
body?: Uint8Array | Reader | string;
}
This would be convenient to have in oak since, for example, dejs renders its templates to a Reader
.
This is a piece of code from Oak:
https://github.com/oakserver/oak/blob/master/application.ts#L25-L35
This incorrectly uses await for each request. As a result, requests cannot be executed in parallel, but are executed serially. If two requests are sent in succession, each of which takes 10s, eventually all requests will be completed in 20s instead of all being completed at the same time in 10s
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use(async ctx => {
await new Promise(resolve => setTimeout(resolve, 10000));
ctx.response.body = "Hello World!";
});
await app.listen({ port: 8000 });
Renaming FileInfo.len to FileInfo.size caused Oak to broke under v0.37 of Deno.
denoland/deno#4338
I wanted to make simple REST API with oak but noticed that there is no body
field on Request
, or worse any way to access underlying ServerRequest
's body. I guess body parsing middleware is missing.
Thanks for maintaining this project!
I want to close down the Oak server each test.
application.use(...routes);
application.listen({ port });
test_code(port);
application.close(); // <-- Something like this
Is this possible?
Olav
Cookies are not working.
Example:
.get(
'/setCookie',
(context) => {
context.cookies.set('auth', JSON.stringify({count:1}))
context.response.body = 'cookie set'
}
)
.get(
'/getCookie',
(context) => {
context.response.body = 'hello' + context.cookies.get('auth')
}
)
This doesn't return the cookie value on the second request.
If I wanted to throw a 500 error through my oak based API, how would I catch an error an being able to return it without Deno throwing as well?
Something like this in oak, would be nice:
app.use(async (ctx, next) => {
try {
await next();
} catch (err) {
//Resolve error here
}
});
The idea is to be able to use a router as path of an another router. Maybe this is supported, if so, sorry for creating a duplicate issue.
Hi,
Apologies if am doing this incorrectly. Noticing route handlers with query params are not matching.
Can reproduce this through examples/routingServer.ts
:
// .get("/book", async (context) => {
// context.response.body = Array.from(books.values());
// })
GET http://127.0.0.1:8000/book?id=1234
404 Not Found
I have copy pasted from the docs to to remove my sketchy typing from the equation :)
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use((ctx) => {
ctx.response.body = "Hello world!";
});
await app.listen("127.0.0.1:8000");
then running deno run --allow-net server.ts
I get 25 errors after compilation that I can paste below for reference:
error TS2322: Type '(_: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'.
Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
► https://deno.land/[email protected]/http/_io.ts:10:5
10 read(_: Uint8Array): Promise<number | null> {
~~~~
error TS2322: Type '(buf: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'.
Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
► https://deno.land/[email protected]/http/_io.ts:35:12
35 return { read };
~~~~
error TS2322: Type '(buf: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'.
Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
► https://deno.land/[email protected]/http/_io.ts:113:12
113 return { read };
~~~~
error TS2339: Property 'iter' does not exist on type 'typeof Deno'.
► https://deno.land/[email protected]/http/_io.ts:167:34
167 for await (const chunk of Deno.iter(r)) {
~~~~
error TS2345: Argument of type 'Reader' is not assignable to parameter of type 'Writer'.
Property 'write' is missing in type 'Reader' but required in type 'Writer'.
► https://deno.land/[email protected]/http/_io.ts:265:31
265 const n = await Deno.copy(r.body, writer);
~~~~~~
'write' is declared here.
► $asset$/lib.deno.ns.d.ts:504:5
504 write(p: Uint8Array): Promise<number>;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2339: Property 'listenTls' does not exist on type 'typeof Deno'.
► https://deno.land/[email protected]/http/server.ts:16:17
16 const { listen, listenTls } = Deno;
~~~~~~~~~
error TS2694: Namespace 'Deno' has no exported member 'ListenTlsOptions'.
► https://deno.land/[email protected]/http/server.ts:289:38
289 export type HTTPSOptions = Omit<Deno.ListenTlsOptions, "transport">;
~~~~~~~~~~~~~~~~
error TS2694: Namespace 'Deno' has no exported member 'ListenTlsOptions'.
► https://deno.land/[email protected]/http/server.ts:309:26
309 const tlsOptions: Deno.ListenTlsOptions = {
~~~~~~~~~~~~~~~~
error TS2694: Namespace 'Deno' has no exported member 'WriterSync'.
► https://deno.land/[email protected]/io/bufio.ts:8:24
8 type WriterSync = Deno.WriterSync;
~~~~~~~~~~
error TS2469: The '>=' operator cannot be applied to type 'symbol'.
► https://deno.land/[email protected]/io/bufio.ts:90:14
90 assert(rr >= 0, "negative read");
~~
error TS2365: Operator '+=' cannot be applied to types 'number' and 'number | unique symbol'.
► https://deno.land/[email protected]/io/bufio.ts:91:7
91 this.w += rr;
~~~~~~~~~~~~
error TS2469: The '>' operator cannot be applied to type 'symbol'.
► https://deno.land/[email protected]/io/bufio.ts:92:11
92 if (rr > 0) {
~~
error TS2416: Property 'read' in type 'BufReader' is not assignable to the same property in base type 'Reader'.
Type '(p: Uint8Array) => Promise<number | null>' is not assignable to type '(p: Uint8Array) => Promise<number | unique symbol>'.
Type 'Promise<number | null>' is not assignable to type 'Promise<number | unique symbol>'.
Type 'number | null' is not assignable to type 'number | unique symbol'.
Type 'null' is not assignable to type 'number | unique symbol'.
► https://deno.land/[email protected]/io/bufio.ts:123:9
123 async read(p: Uint8Array): Promise<number | null> {
~~~~
error TS2469: The '>=' operator cannot be applied to type 'symbol'.
► https://deno.land/[email protected]/io/bufio.ts:133:16
133 assert(nread >= 0, "negative read");
~~~~~
error TS2322: Type 'number | unique symbol' is not assignable to type 'number | null'.
Type 'unique symbol' is not assignable to type 'number | null'.
► https://deno.land/[email protected]/io/bufio.ts:138:9
138 return rr;
~~~~~~~~~~
error TS2322: Type 'number | unique symbol' is not assignable to type 'number | null'.
Type 'unique symbol' is not assignable to type 'number | null'.
► https://deno.land/[email protected]/io/bufio.ts:145:7
145 rr = await this.rd.read(this.buf);
~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/_constants.ts:51:19
51 const isWindows = build.os == "windows";
~~~~~~~~~~~~~~~~~~~~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/_globrex.ts:5:15
5 const isWin = Deno.build.os === "windows";
~~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/mod.ts:7:19
7 const isWindows = Deno.build.os == "windows";
~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2345: Argument of type 'string | URL' is not assignable to parameter of type 'string'.
Type 'URL' is not assignable to type 'string'.
► https://deno.land/[email protected]/path/posix.ts:433:18
433 return new URL(url).pathname;
~~~
error TS2367: This condition will always return 'false' since the types 'OperatingSystem' and '"windows"' have no overlap.
► https://deno.land/[email protected]/path/separator.ts:2:19
2 const isWindows = Deno.build.os == "windows";
~~~~~~~~~~~~~~~~~~~~~~~~~~
error TS2339: Property 'get' does not exist on type '{ (): { [index: string]: string; }; (key: string): string | undefined; }'.
► https://deno.land/[email protected]/path/win32.ts:42:18
42 path = env.get(=${resolvedDevice}
) || cwd();
~~~
error TS2345: Argument of type 'string | URL' is not assignable to parameter of type 'string'.
Type 'URL' is not assignable to type 'string'.
► https://deno.land/[email protected]/path/win32.ts:911:18
911 return new URL(url).pathname
~~~
error TS2339: Property 'mtime' does not exist on type 'FileInfo'.
► https://deno.land/x/oak/send.ts:151:55
151 if (!response.headers.has("Last-Modified") && stats.mtime) {
~~~~~
error TS2339: Property 'mtime' does not exist on type 'FileInfo'.
► https://deno.land/x/oak/send.ts:152:49
152 response.headers.set("Last-Modified", stats.mtime.toUTCString());
~~~~~
The documentation shows "params" as a variable attached to the "context", but the type definition is missing the params for some reason, so the question is, are there two different types of context in the module? why does using context without explicit type works, but when giving an explicit type it fails?
using deno 1.0
import { Context, Router } from "https://deno.land/x/oak/mod.ts";
const router = new Router();
// Breaks when compiling...
router.get('/', (ctx: Context) => {
console.log(ctx.params);
})
// Doesn't break when compiling
router.get('/', ctx => {
console.log(ctx.params);
})
Seems like the issue is simply that the field doesn't exist on the Context class, so to fix it we just need to add "params: Record<string, any>" to the class in this file...
https://github.com/oakserver/oak/blob/master/context.ts
Currently there is no way to work with mime types in requests that are not of the hard-coded types.
For example text
has only this https://github.com/oakserver/oak/blob/master/request.ts#L26
A rawBody
method would help future proof the API so it can used to read raw bytes.
Additionally providing a way to inject different text mime-types would also be good for the safe body
method.
version: 4.0.0
The issue is, the error is expected to be caught, and it is when throwing from app.use()
, but when called from the router, the error makes the server crash.
const router = new Router();
app.use(async (ctx, next) => {
try {
await next();
} catch(err) {
console.log(err); // <-- this is not called
}
})
// I throw an error here and expect it to be caught, or sent to the client, but the server crashes instead
router.get(ctx => ctx.throw(500));
app.use(router.routes());
app.use(router.allowedMethods());
await app.listen({ port: 8000 });
I'm developing simple API with oak, I want to return simple 404 response.
function notFound(context: Context) {
context.response.status = Status.NotFound;
}
code above causes server to hang because there is no body in response.
If you do:
function notFound(context: Context) {
context.response.status = Status.NotFound;
context.response.body = "";
}
everything's working correctly.
Is this a bug or did I forget about something?
Thank you for this beautiful work!
Anyway I call ctx.request.body()
forces the endpoint to Error out and not console.log() or add a response body
import { Application, Router } from "https://deno.land/x/oak/mod.ts"
let port = 8084,
router = new Router(),
app = new Application()
router
.post('/wtf', async ctx => {
let body = await ctx.request.body()
console.log(body)
ctx.response.body = { hello: 'world' }
})
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(`0.0.0.0:${ port }`)
I'm not suggesting to disregard the deno_std version altogether, but ass of right now - without #19 -oak
is incompatible with the latest version of Deno because all deps are pinned to v0.9.0. Obviously there are major benefits to having releases pinned to the Deno runtime version it was developed for, but it would be nice to at least have a version of oak
without the dependencies pinned to a specific Deno version.
This could be in the form of the master
branch or a latest
/unpinned
tagged release that keeps getting updated.
Both of the examples fail with both Deno 0.10 and 0.11 with the following errors;
$ deno index.ts --allow-read --allow-net
Compile file:///Users/bevan/projects/denoworld/index.ts
error TS2694: Namespace 'Deno' has no exported member 'ReadResult'.
► https://deno.land/[email protected]/io/bufio.ts:7:24
7 type ReadResult = Deno.ReadResult;
~~~~~~~~~~
error TS2339: Property 'nread' does not exist on type 'number'.
► https://deno.land/[email protected]/io/bufio.ts:134:19
134 assert(rr.nread >= 0, "negative read");
~~~~~
Found 2 errors.
On macos 10.13.6 High Sierra;
$ deno version
deno: 0.12.0
v8: 7.7.200
typescript: 3.5.1
A file called app.ts was created with the following code:
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
app.use(ctx => {
ctx.response.body = "Hello World!";
});
console.log("Listening.....");
await app.listen({ port: 8000 });
Subsequently, the following command was executed:
deno --allow-net app.ts
Expected deno to compile the code successfully and see the following line in stdout:
Listening.....
Compilation failed with the following error:
Compile file:///home/angad/Desktop/covidcomm/covidcomm/app.ts
error TS2349: This expression is not callable.
Type 'Boolean' has no call signatures.
► https://deno.land/x/oak/send.ts:62:36
62 return (await Deno.stat(path)).isFile();
~~~~~~
error TS2349: This expression is not callable.
Type 'Boolean' has no call signatures.
► https://deno.land/x/oak/send.ts:139:15
139 if (stats.isDirectory()) {
~~~~~~~~~~~
Found 2 errors.
Package | Version |
---|---|
deno | 0.41.0 |
v8 | 8.2.308 |
typescript | 3.8.3 |
export class ApplicationErrorEvent<S extends State> extends ErrorEvent { ^ at application.ts:78:61
The params
field seems to be missing from the Context
type.
See https://doc.deno.land/https/deno.land/x/oak/mod.ts#Context
Currently working around this by:
router.get("/:name", (
ctx: oak.Context & {params: { name: string } }
) => {...});
I'd like to use Oak to proxy API requests onto another server, while overriding some with other responses and/or serving up local static assets for others. A proxy middleware would be nice.
Based on the RouterOptions interface, it seems like I should be able to specify a prefix for a router by declaring a new router like so:
const router = new Router({
prefix: 'example',
});
However, it seems the Router constructor doesn't actually do anything with the prefix router option.
I cloned the repo and fixed this for personal use. If you're interested I could create a PR. Do you already have this addition on your radar?
Steps to reproduce
error TS2345: Argument of type 'string | undefined' is not assignable to parameter of type 'string'.
Type 'undefined' is not assignable to type 'string'.
► file:///Users/calebmchenry/code/sandbox/deno-server/src/server.ts:20:41
20 context.response.body = books.get(context.params.id);
Edit:
deno --version
deno 0.40.0
v8 8.2.308
typescript 3.8.3
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.