1

I come from a land of ASP.NET Core. Having fun learning a completely new stack.

I'm used to being able to:

  1. name a route "orders"
  2. give it a path like /customer-orders/{id}
  3. register it
  4. use the routing system to build a URL for my named route

An example of (4) might be to pass a routeName and then routeValues which is an object like { id = 193, x = "y" } and the routing system can figure out the URL /customer-orders/193?x=y - notice how it just appends extraneous key-vals as params.

Can I do something like this in oak on Deno?? Thanks.

Update: I am looking into some functions on the underlying regexp tool the routing system uses. It doesn't seem right that this often used feature should be so hard/undiscoverable/inaccessible.

https://github.com/pillarjs/path-to-regexp#compile-reverse-path-to-regexp

Luke Puplett
  • 42,091
  • 47
  • 181
  • 266
  • Did you read the [documentation](https://deno.land/x/oak@v11.1.0), including the Router section (linked)? If so, what was confusing? – jsejcksn Nov 30 '22 at 23:51
  • Hey Jesse(?) I am the odd guy that reads the docs fully before writing any code! I sometimes make notes in public https://github.com/lukepuplett/notes though I didn't for oak. Anyway, there's everything about routes and matching a URL but not building a URL - unless I'm blind. I will read it all again. – Luke Puplett Dec 01 '22 at 10:43
  • [^](https://stackoverflow.com/questions/74635313/oak-on-deno-how-do-i-build-a-url-to-a-route?noredirect=1#comment131748001_74635313) No worries. I asked because — while it's not unfair to point out that SO is full of [answers that are essentially rehashed info from documentation](https://stackoverflow.com/a/74635291/438273), that's not exactly the purpose of the site, and — if you can better pinpoint what it is that's not covered by the examples in the docs, you will probably get a better answer. TS/JS isn't ASP.NET and concepts aren't the same — not everything translates exactly. – jsejcksn Dec 01 '22 at 11:14
  • It seems like you might be asking more than one question. I provided an answer about working with the incoming request URL. If you'd like to learn about building HTML for use in a response, there's already lots of documentation on this site (and elsewhere) covering that. – jsejcksn Dec 01 '22 at 12:46

2 Answers2

1

I'm not exactly sure what you mean by "building" a URL, but the URL associated to the incoming request is defined by the requesting client, and is available in each middleware callback function's context parameter at context.request.url as an instance of the URL class.

The documentation provides some examples of using a router and the middleware callback functions that are associated to routes in Oak.

Here's an example module which demonstrates accessing the URL-related data in a request:

so-74635313.ts:

import { Application, Router } from "https://deno.land/x/oak@v11.1.0/mod.ts";

const router = new Router({ prefix: "/customer-orders" });

router.get("/:id", async (ctx, next) => {
  // An instance of the URL class:
  const { url } = ctx.request;

  // An instance of the URLSearchParams class:
  const { searchParams } = url;

  // A string:
  const { id } = ctx.params;

  const serializableObject = {
    id,
    // Iterate all the [key, value] entries and collect into an array:
    searchParams: [...searchParams.entries()],
    // A string representation of the full request URL:
    url: url.href,
  };

  // Respond with the object as JSON data:
  ctx.response.body = serializableObject;
  ctx.response.type = "application/json";

  // Log the object to the console:
  console.log(serializableObject);

  await next();
});

const app = new Application();

app.use(router.routes());
app.use(router.allowedMethods());

function printStartupMessage({ hostname, port, secure }: {
  hostname: string;
  port: number;
  secure?: boolean;
}): void {
  if (!hostname || hostname === "0.0.0.0") hostname = "localhost";
  const address =
    new URL(`http${secure ? "s" : ""}://${hostname}:${port}/`).href;
  console.log(`Listening at ${address}`);
  console.log("Use ctrl+c to stop");
}

app.addEventListener("listen", printStartupMessage);

await app.listen({ port: 8000 });

In a terminal shell (I'll call it shell A), the program is started:

% deno run --allow-net so-74635313.ts
Listening at http://localhost:8000/
Use ctrl+c to stop

Then, in another shell (I'll call it shell B), a network request is sent to the server at the route described in your question — and the response body (JSON text) is printed below the command:

% curl 'http://localhost:8000/customer-orders/193?x=y'
{"id":"193","searchParams":[["x","y"]],"url":"http://localhost:8000/customer-orders/193?x=y"}

Back in shell A, the output of the console.log statement can be seen:

{
  id: "193",
  searchParams: [ [ "x", "y" ] ],
  url: "http://localhost:8000/customer-orders/193?x=y"
}

ctrl + c is used to send an interrupt signal (SIGINT) to the deno process and stop the server.

jsejcksn
  • 27,667
  • 4
  • 38
  • 62
  • If this didn't address the question completely, then hopefully it provides you with enough context to understand the difference between how I interpreted your question and what you intended to communicate/ask. Perhaps your question was more about using the built-in `URL` class (linked in the question)? If so, then MDN will document how to work with that class. At any rate: let me know if there's a dimension to the question that I didn't cover in the answer. – jsejcksn Dec 01 '22 at 12:38
  • 1
    I wanted to thank you for your time today with trying to help me. It's really appreciated, and I apologise for not making clear what I was trying to do. – Luke Puplett Dec 01 '22 at 14:07
1

I am fortunately working with a React developer today!

Between us, we've found the .url(routeName, ...) method on the Router instance and that does exactly what I need!

Here's the help for it:

  /** Generate a URL pathname for a named route, interpolating the optional
   * params provided.  Also accepts an optional set of options. */

Here's it in use in context:

export const routes = new Router()
  .get(
    "get-test",
    "/test",
    handleGetTest,
  );

function handleGetTest(context: Context) {
  console.log(`The URL for the test route is: ${routes.url("get-test")}`);
}

// The URL for the test route is: /test
Luke Puplett
  • 42,091
  • 47
  • 181
  • 266