Skip to content

Commit

Permalink
fixup! refactor(coap-server): refactor handleRequest method
Browse files Browse the repository at this point in the history
  • Loading branch information
JKRhb committed Jul 21, 2023
1 parent c7b23d7 commit 248f19f
Showing 1 changed file with 68 additions and 60 deletions.
128 changes: 68 additions & 60 deletions packages/binding-coap/src/coap-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,14 +333,21 @@ export default class CoapServer implements ProtocolServer {
*
* @param req The incoming request.
* @param res The outgoing response.
* @param thing The ExposedThing whose TD is requested.
* @param thingKey The key of the ExposedThing whose TD is requested.
*/
private async handleTdRequest(req: IncomingMessage, res: OutgoingMessage, thing: ExposedThing) {
private async handleTdRequest(req: IncomingMessage, res: OutgoingMessage, thingKey: string) {
if (req.method !== "GET") {
this.sendErrorResponse(res, "4.05", "Method Not Allowed");
return;
}

const thing = this.things.get(thingKey);

if (thing == null) {
this.sendErrorResponse(res, "4.04", "Not Found");
return;
}

const accept = req.headers.Accept;

const contentSerdes = ContentSerdes.get();
Expand Down Expand Up @@ -378,32 +385,18 @@ export default class CoapServer implements ProtocolServer {
);
});

let contentType;
const contentType = this.getContentTypeFromRequest(req);

try {
contentType = this.getContentTypeFromRequest(req);
} catch (exception) {
// FIXME
this.sendErrorResponse(res, "415", exception.msg);
if (!this.checkContentTypeSupportForInput(res, req.method, contentType)) {
this.sendErrorResponse(res, "4.15", "Unsupported Media Type");
return;
}

const requestUri = this.processRequestUri(req);
const segments = decodeURI(requestUri).split("/");
const { thingKey, affordanceType, affordanceKey } = this.parseUriSegments(requestUri);

if (requestUri === "/") {
// no path -> list all Things
if (req.method !== "GET") {
this.sendErrorResponse(res, "4.05", "Method Not Allowed");
return;
}

res.setHeader("Content-Format", ContentSerdes.DEFAULT);
res.code = "2.05";
const payload = JSON.stringify(this.getThingDescriptionPayload());
res.end(payload);

// resource found and response sent
this.handleThingsRequest(req, res);

Check failure on line 399 in packages/binding-coap/src/coap-server.ts

View workflow job for this annotation

GitHub Actions / setup-and-test (ubuntu-latest, 16.x)

Argument of type 'IncomingMessage' is not assignable to parameter of type 'string'.

Check failure on line 399 in packages/binding-coap/src/coap-server.ts

View workflow job for this annotation

GitHub Actions / setup-and-test (ubuntu-latest, 18.x)

Argument of type 'IncomingMessage' is not assignable to parameter of type 'string'.
return;
}

Expand All @@ -412,23 +405,11 @@ export default class CoapServer implements ProtocolServer {
return;
}

// path -> select Thing
const thing = this.things.get(segments[1]);

if (thing == null) {
this.sendErrorResponse(res, "4.04", "Not Found");
return;
}

const affordanceType = segments[2];
if (segments.length === 2 || affordanceType === "") {
// Thing root -> send TD
await this.handleTdRequest(req, res, thing);
if (affordanceType == null || affordanceType === "") {
await this.handleTdRequest(req, res, thingKey);
return;
}

const affordanceKey = segments[3];

switch (affordanceType) {
case this.PROPERTY_DIR:
this.handlePropertyRequest(thing, affordanceKey, req, res, contentType);

Check failure on line 415 in packages/binding-coap/src/coap-server.ts

View workflow job for this annotation

GitHub Actions / setup-and-test (ubuntu-latest, 16.x)

Cannot find name 'thing'.

Check failure on line 415 in packages/binding-coap/src/coap-server.ts

View workflow job for this annotation

GitHub Actions / setup-and-test (ubuntu-latest, 18.x)

Cannot find name 'thing'.
Expand All @@ -454,6 +435,18 @@ export default class CoapServer implements ProtocolServer {
return uri;
}

private handleThingsRequest(method: string, res: OutgoingMessage) {
if (method !== "GET") {
this.sendErrorResponse(res, "4.05", "Method Not Allowed");
return;
}

res.setHeader("Content-Format", ContentSerdes.DEFAULT);
res.code = "2.05";
const payload = JSON.stringify(this.getThingDescriptionPayload());
res.end(payload);
}

private async handlePropertyRequest(
thing: ExposedThing,
affordanceKey: string,
Expand Down Expand Up @@ -596,6 +589,7 @@ export default class CoapServer implements ProtocolServer {
const action = thing.actions[affordanceKey];

if (action == null) {
this.sendErrorResponse(res, "4.04", "Not Found");
return;
}

Expand Down Expand Up @@ -638,10 +632,10 @@ export default class CoapServer implements ProtocolServer {
res: OutgoingMessage,
contentType?: string
) {
// sub-path -> select Event
const event = thing.events[affordanceKey];

if (event == null) {
this.sendErrorResponse(res, "4.04", "Not Found");
return;
}

Expand All @@ -650,8 +644,19 @@ export default class CoapServer implements ProtocolServer {
return;
}

// subscribeevent
if (req.headers.Observe === 0) {
const observe = req.headers.Observe;

if (observe == null) {
debug(
`CoapServer on port ${this.getPort()} rejects '${affordanceKey}' read from ${Helpers.toUriLiteral(
req.rsinfo.address
)}:${req.rsinfo.port}`
);
this.sendErrorResponse(res, "4.00", "No Observe Option");
return;
}

if (observe === 0) {
// work-around to avoid duplicate requests (resend due to no response)
// (node-coap does not deduplicate when Observe is set)
const packet = res._packet;
Expand Down Expand Up @@ -703,7 +708,7 @@ export default class CoapServer implements ProtocolServer {
);
thing.handleUnsubscribeEvent(affordanceKey, listener, options);
});
} else if (req.headers.Observe > 0) {
} else if (observe > 0) {
debug(
`CoapServer on port ${this.getPort()} sends '${affordanceKey}' response to ${Helpers.toUriLiteral(
req.rsinfo.address
Expand All @@ -712,34 +717,27 @@ export default class CoapServer implements ProtocolServer {
// TODO: Check if this has been fixed in the meantime
// node-coap does not support GET cancellation
this.sendErrorResponse(res, "5.01", "node-coap issue: no GET cancellation, send RST");
} else {
debug(
`CoapServer on port ${this.getPort()} rejects '${affordanceKey}' read from ${Helpers.toUriLiteral(
req.rsinfo.address
)}:${req.rsinfo.port}`
);
res.code = "4.00";
res.end("No Observe Option");
}
}

private getContentTypeFromRequest(req: IncomingMessage): string | undefined {
private getContentTypeFromRequest(req: IncomingMessage): string {
const contentType = req.headers["Content-Format"] as string;

if (req.method === "PUT" || req.method === "POST") {
if (contentType != null && req.payload.length > 0) {
warn(
`CoapServer on port ${this.getPort()} received no Content-Format from ${Helpers.toUriLiteral(
req.rsinfo.address
)}:${req.rsinfo.port}`
);
return ContentSerdes.DEFAULT;
} else if (ContentSerdes.get().getSupportedMediaTypes().includes(ContentSerdes.getMediaType(contentType))) {
throw Error("Unsupported Media Type");
}
if (contentType == null) {
warn(
`CoapServer on port ${this.getPort()} received no Content-Format from ${Helpers.toUriLiteral(
req.rsinfo.address
)}:${req.rsinfo.port}`
);
}

return undefined;
return contentType ?? ContentSerdes.DEFAULT;
}

private checkContentTypeSupportForInput(res: OutgoingMessage, method: string, contentType: string) {
const methodsWithPayload: string[] = ["PUT", "POST", "FETCH", "iPATCH", "PATCH"];

return methodsWithPayload.includes(method) && ContentSerdes.get().getSupportedMediaTypes().includes(ContentSerdes.getMediaType(contentType));
}

private getThingDescriptionPayload() {
Expand All @@ -753,6 +751,16 @@ export default class CoapServer implements ProtocolServer {
);
}

private parseUriSegments(requestUri: string) {
const segments = decodeURI(requestUri).split("/");

return {
thingKey: segments[1],
affordanceType: segments[2],
affordanceKey: segments[3],
}
}

private sendErrorResponse(res: OutgoingMessage, errorCode: string, errorMessage: string) {
res.code = errorCode;
res.end(errorMessage);
Expand Down

0 comments on commit 248f19f

Please sign in to comment.