Skip to content

Commit

Permalink
[NO-ISSUE] Audit of outstanding missing features (#7)
Browse files Browse the repository at this point in the history
- fix: only set `x-powered-by` header if it is enabled as a setting.
- feat: add missing methods to `response.md` API docs: `unset` and `etag`.
- chore: audit of feature gap between Express and Opine. Available as TODOs in the code.
  • Loading branch information
asos-craigmorten authored May 28, 2020
1 parent 24b417c commit 7f058ec
Show file tree
Hide file tree
Showing 11 changed files with 102 additions and 9 deletions.
16 changes: 16 additions & 0 deletions .github/API/response.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,14 @@ await res.end();
await res.setStatus(404).end();
```

#### res.etag(data)

Sets the response `ETag` HTTP header using the specified `data` parameter. The etag implementation used is determined by the [etag application setting](./application.md#application-settings).

```ts
res.etag(fileStat);
```

#### res.get(field)

Returns the HTTP response header specified by `field`. The match is case-insensitive.
Expand Down Expand Up @@ -401,3 +409,11 @@ res.type("application/json");
res.type("png");
// => 'image/png'
```

#### res.unset(field)

Remove the response's HTTP header `field`.

```ts
res.set("Content-Type");
```
6 changes: 6 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# ChangeLog

## [0.5.2] - 28-05-2020

- fix: only set `x-powered-by` header if it is enabled as a setting.
- feat: add missing methods to `response.md` API docs: `unset` and `etag`.
- chore: audit of feature gap between Express and Opine. Available as TODOs in the code.

## [0.5.1] - 27-05-2020

- fix: missing location method type
Expand Down
18 changes: 15 additions & 3 deletions src/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ const create = Object.create;
const setPrototypeOf = Object.setPrototypeOf;
const slice = Array.prototype.slice;

// TODO: move app over to class based?

/**
* Application prototype.
*
Expand Down Expand Up @@ -56,9 +58,15 @@ app.init = function init(): void {
app.defaultConfiguration = function defaultConfiguration(): void {
this.enable("x-powered-by");
this.set("etag", "weak");
// TODO: env
// TODO: query parser
// TODO: subdomain offset
// TODO: trust proxy

const self: Opine = this as Opine;
this.on("mount", function onmount(parent: Opine) {
// TODO: trust proxy

// inherit prototypes
setPrototypeOf(self.request, parent.request);
setPrototypeOf(self.response, parent.response);
Expand All @@ -74,6 +82,7 @@ app.defaultConfiguration = function defaultConfiguration(): void {
// default locals
this.locals.settings = this.settings;

// TODO: views
this.set("jsonp callback name", "callback");
};

Expand All @@ -91,6 +100,7 @@ app.lazyrouter = function lazyrouter(): void {
caseSensitive: this.enabled("case sensitive routing"),
strict: this.enabled("strict routing"),
});
// TODO: query parser
this._router.use(query());
this._router.use(init(this as Opine));
}
Expand Down Expand Up @@ -193,9 +203,9 @@ app.route = function route(prefix: PathParams): IRoute {
return this._router.route(prefix);
};

// TODO: app.engine
// TODO: app.engine()

// TODO: app.param
// TODO: app.param()

/**
* Assign `setting` to `val`, or return `setting`'s value.
Expand Down Expand Up @@ -343,8 +353,10 @@ app.all = function all(path: PathParams): Application {
return this;
};

// TODO: app.render
// TODO: app.render()

// TODO: consider adding optional callback to ease Express transition.
// TODO: consider using a Proxy to enable setting / getting of `req.body`.
/**
* Listen for connections.
*
Expand Down
5 changes: 3 additions & 2 deletions src/middleware/bodyParser/read.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,11 +93,12 @@ function getBodyReader(req: Request, inflate: boolean = true) {
);
}

// TODO: support deflate and gzip encoding.
switch (encoding) {
case "identity":
return req.body;
case "deflate": // TODO:
case "gzip": // TODO:
case "deflate":
case "gzip":
default:
throw createHttpError(
415,
Expand Down
2 changes: 1 addition & 1 deletion src/middleware/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const setPrototypeOf = Object.setPrototypeOf;
*/
export const init = function (app: Opine) {
return function opineInit(req: Request, res: Response, next: NextFunction) {
res.set("X-Powered-By", "Opine");
if (app.enabled("x-powered-by")) res.set("X-Powered-By", "Opine");

req.res = res;
res.req = req;
Expand Down
2 changes: 2 additions & 0 deletions src/middleware/query.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { parseUrl } from "../utils/parseUrl.ts";
import { Request, Response, NextFunction, ParsedURL } from "../types.ts";

// TODO: back-compat support for Express signature. Namely an
// `options` parameter allowing for custom query parsers.
/**
* Exposes a query object containing the querystring
* parameters of the request url.
Expand Down
7 changes: 6 additions & 1 deletion src/middleware/serveStatic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ import {
ParsedURL,
} from "../types.ts";

// TODO: header options, and various other error handling, see:
// - notes in response.ts for `res.sendFile()`
// - notes in response.ts for `res.download()`
// - https://github.com/expressjs/serve-static/#options
/**
* Serve static files.
*
* @param {string} root
* @param {object} [options]
* @return {Handler}
* @public
*/
// TODO: header options - see https://github.com/expressjs/serve-static/#options
export function serveStatic(root: string, options: any = {}): Handler {
// fall-though
const fallthrough = options.fallthrough !== false;
Expand Down
34 changes: 34 additions & 0 deletions src/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,36 @@ request.get = function get(name: string): string {
}
};

// TODO: req.accepts()

// TODO: req.acceptsEncodings()

// TODO: req.acceptsCharsets()

// TODO: req.acceptsLanguages()

// TODO: req.range()

// TODO: req.param()

// TODO: req.is()

// TODO: req.protocol

// TODO: req.secure

// TODO: req.ip

// TODO: req.ips

// TODO: req.subdomains

// TODO: req.path

// TODO: req.hostname

// TODO: req.host

/**
* Check if the request is fresh, aka
* Last-Modified and/or the ETag
Expand Down Expand Up @@ -74,3 +104,7 @@ defineGetter(request, "fresh", function (this: Request): boolean {

return false;
});

// TODO: req.stale

// TODO: req.xhr
17 changes: 16 additions & 1 deletion src/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export class Response implements DenoResponse {
req!: Request;
locals!: any;

// TODO: Supporting arrays.
/**
* Append additional header `field` with value `val`.
*
Expand Down Expand Up @@ -69,6 +70,7 @@ export class Response implements DenoResponse {
return this;
}

// TODO: back-compat support for Express signature.
/**
* Set a cookie. Sets the cookie path to "/" if not defined.
*
Expand All @@ -91,6 +93,7 @@ export class Response implements DenoResponse {
return this;
}

// TODO: back-compat support for Express signature.
/**
* Clear a cookie.
*
Expand All @@ -105,6 +108,7 @@ export class Response implements DenoResponse {
return this;
}

// TODO: back-compat support for Express signature. i.e. support options.
/**
* Transfer the file at the given `path` as an attachment.
*
Expand Down Expand Up @@ -161,7 +165,7 @@ export class Response implements DenoResponse {
*
* @param {string|Uint8Array|Deno.FileInfo} chunk
* @returns {Response} for chaining
* @publics
* @public
*/
etag(chunk: string | Uint8Array | Deno.FileInfo): this {
const etagFn = this.app.get("etag fn");
Expand Down Expand Up @@ -389,6 +393,15 @@ export class Response implements DenoResponse {
return this;
}

// TODO: back-compat support for Express signature. Specifically options
// parameter, but likely not callback. Should support:
//
// - abort handling
// - directory handling
// - error handling - see https://github.com/pillarjs/send/blob/master/index.js#L267
// - `options` - see https://github.com/pillarjs/send#sendreq-path-options
// - other headers: 'Accept-Ranges', 'Cache-Control', 'Content-Range'

/**
* Transfer the file at the given `path`.
*
Expand Down Expand Up @@ -438,6 +451,8 @@ export class Response implements DenoResponse {
return this.send(body);
}

// TODO: back-compat support for Express signature.
// Namely objects and arrays.
/**
* Set header `field` to `value`, or pass
* an object of header fields.
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Type definitions for Opine
// Definitions by: Craig Morten <https://github.com/asos-craigmorten>
// TODO: consider integrating these types into the app files themselves
// rather than having a separate file.

import {
ServerRequest as DenoServerRequest,
Expand Down
2 changes: 1 addition & 1 deletion version.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Version of Opine.
*/
export const VERSION: string = "0.5.1";
export const VERSION: string = "0.5.2";

/**
* Supported version of Deno.
Expand Down

0 comments on commit 7f058ec

Please sign in to comment.