Skip to content

Commit

Permalink
v2
Browse files Browse the repository at this point in the history
  • Loading branch information
ForsakenHarmony committed Mar 28, 2023
1 parent be95cf2 commit 2a05f95
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 57 deletions.
35 changes: 19 additions & 16 deletions packages/next-swc/crates/next-core/js/src/entry/router.ts
@@ -1,9 +1,9 @@
import type { Ipc } from "@vercel/turbopack-next/ipc/index";
import type { Ipc, StructuredError } from "@vercel/turbopack-next/ipc/index";
import type { IncomingMessage, ServerResponse } from "node:http";
import { Buffer } from "node:buffer";
import { createServer, makeRequest } from "@vercel/turbopack-next/ipc/server";
import { toPairs } from "@vercel/turbopack-next/internal/headers";
import { makeResolver } from "next/dist/server/lib/route-resolver";
import { makeResolver, RouteResult } from "next/dist/server/lib/route-resolver";
import loadConfig from "next/dist/server/config";
import { PHASE_DEVELOPMENT_SERVER } from "next/dist/shared/lib/constants";

Expand All @@ -22,16 +22,6 @@ type RouterRequest = {
rawQuery: string;
};

type RouteResult =
| {
type: "rewrite";
url: string;
headers: Record<string, string>;
}
| {
type: "none";
};

type IpcOutgoingMessage = {
type: "value";
data: string | Buffer;
Expand All @@ -44,6 +34,10 @@ type MessageData =
type: "rewrite";
data: RewriteResponse;
}
| {
type: "error";
error: StructuredError;
}
| { type: "none" };

type RewriteResponse = {
Expand Down Expand Up @@ -155,15 +149,24 @@ async function handleClientResponse(
return {
type: "none",
};
case "error":
return {
type: "error",
error: data.error,
};
case "rewrite":
default:
return {
type: "rewrite",
data: {
url: data.url,
headers: Object.entries(data.headers),
headers: Object.entries(data.headers)
.filter(([, val]) => val != null)
.map(([name, value]) => [name, value!.toString()]),
},
};
default:
// @ts-expect-error data.type is never
throw new Error(`unknown route result type: ${data.type}`);
}
}

Expand All @@ -172,7 +175,7 @@ async function handleClientResponse(
headers: toPairs(clientResponse.rawHeaders),
};

ipc.send({
await ipc.send({
type: "value",
data: JSON.stringify({
type: "middleware-headers",
Expand All @@ -181,7 +184,7 @@ async function handleClientResponse(
});

for await (const chunk of clientResponse) {
ipc.send({
await ipc.send({
type: "value",
data: JSON.stringify({
type: "middleware-body",
Expand Down
52 changes: 44 additions & 8 deletions packages/next-swc/crates/next-core/src/router.rs
Expand Up @@ -32,7 +32,7 @@ use turbopack_ecmascript::{
use turbopack_node::{
evaluate::evaluate,
execution_context::{ExecutionContext, ExecutionContextVc},
source_map::StructuredError,
source_map::{StructuredError, trace_stack},
};

use crate::{
Expand Down Expand Up @@ -108,7 +108,7 @@ enum RouterIncomingMessage {
MiddlewareHeaders { data: MiddlewareHeadersResponse },
MiddlewareBody { data: Vec<u8> },
None,
Error(StructuredError),
Error { error: StructuredError },
}

#[turbo_tasks::value(eq = "manual", cell = "new", serialization = "none")]
Expand All @@ -120,13 +120,13 @@ pub struct MiddlewareResponse {
pub body: Stream<Result<Bytes, SharedError>>,
}

#[derive(Debug)]
#[turbo_tasks::value(eq = "manual", cell = "new", serialization = "none")]
#[derive(Debug)]
pub enum RouterResult {
Rewrite(RewriteResponse),
Middleware(MiddlewareResponse),
None,
Error,
Error(String),
}

#[turbo_tasks::function]
Expand Down Expand Up @@ -375,16 +375,36 @@ async fn route_internal(
JsonValueVc::cell(dir.to_string_lossy().into()),
],
CompletionsVc::all(vec![next_config_changed, routes_changed]),
// true,
/* debug */ false,
)
.await?;

let mut read = result.read();

let Some(Ok(first)) = read.next().await else {
return Ok(RouterResult::Error.cell());
let first = match read.next().await {
Some(Ok(first)) => first,
Some(Err(e)) => {
return Ok(
RouterResult::Error(format!("received error from javascript stream: {}", e)).cell(),
)
}
None => {
return Ok(RouterResult::Error(
"no message received from javascript stream".to_string(),
)
.cell())
}
};
let first: RouterIncomingMessage = parse_json_with_source_context(first.to_str()?)?;
let first: RouterIncomingMessage = parse_json_with_source_context(first.to_str()?)
.with_context(|| {
format!(
"parsing incoming message ({})",
first
.to_str()
.expect("this was already successfully converted")
)
})?;

let (res, read) = match first {
RouterIncomingMessage::Rewrite { data } => (RouterResult::Rewrite(data), Some(read)),
Expand Down Expand Up @@ -416,7 +436,23 @@ async fn route_internal(
}

RouterIncomingMessage::None => (RouterResult::None, Some(read)),
_ => (RouterResult::Error, Some(read)),
RouterIncomingMessage::Error { error } => {
bail!(
trace_stack(
error,
router_asset,
chunking_context.output_root(),
project_path
)
.await?
)
}
RouterIncomingMessage::MiddlewareBody { .. } => (
RouterResult::Error(
"unexpected incoming middleware body without middleware headers".to_string(),
),
Some(read),
),
};

// Middleware will naturally drain the full stream, but the rest only take a
Expand Down
4 changes: 2 additions & 2 deletions packages/next-swc/crates/next-core/src/router_source.rs
Expand Up @@ -130,8 +130,8 @@ impl ContentSource for NextRouterContentSource {
.with_context(|| anyhow!("failed to fetch /{path}{}", formated_query(raw_query)))?;

Ok(match &*res {
RouterResult::Error => bail!(
"error during Next.js routing for /{path}{}",
RouterResult::Error(e) => bail!(
"error during Next.js routing for /{path}{}: {e}",
formated_query(raw_query)
),
RouterResult::None => this
Expand Down
4 changes: 3 additions & 1 deletion packages/next/src/server/base-http/index.ts
@@ -1,4 +1,4 @@
import type { IncomingHttpHeaders } from 'http'
import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'http'
import type { I18NConfig } from '../config-shared'

import { PERMANENT_REDIRECT_STATUS } from '../../shared/lib/constants'
Expand Down Expand Up @@ -55,6 +55,8 @@ export abstract class BaseNextResponse<Destination = any> {
*/
abstract getHeader(name: string): string | undefined

abstract getHeaders(): OutgoingHttpHeaders

abstract body(value: string): this

abstract send(): void
Expand Down
5 changes: 5 additions & 0 deletions packages/next/src/server/base-http/node.ts
Expand Up @@ -7,6 +7,7 @@ import { parseBody } from '../api-utils/node'
import { NEXT_REQUEST_META, RequestMeta } from '../request-meta'

import { BaseNextRequest, BaseNextResponse } from './index'
import { OutgoingHttpHeaders } from 'node:http'

type Req = IncomingMessage & {
[NEXT_REQUEST_META]?: RequestMeta
Expand Down Expand Up @@ -103,6 +104,10 @@ export class NodeNextResponse extends BaseNextResponse<Writable> {
return Array.isArray(values) ? values.join(',') : undefined
}

getHeaders(): OutgoingHttpHeaders {
return this._res.getHeaders()
}

appendHeader(name: string, value: string): this {
const currentValues = this.getHeaderValues(name) ?? []

Expand Down
6 changes: 5 additions & 1 deletion packages/next/src/server/base-http/web.ts
@@ -1,4 +1,4 @@
import type { IncomingHttpHeaders } from 'http'
import type { IncomingHttpHeaders, OutgoingHttpHeaders } from 'http'

import { BaseNextRequest, BaseNextResponse } from './index'

Expand Down Expand Up @@ -74,6 +74,10 @@ export class WebNextResponse extends BaseNextResponse<WritableStream> {
return this.headers.get(name) ?? undefined
}

getHeaders(): OutgoingHttpHeaders {
return Object.fromEntries(this.headers.entries())
}

hasHeader(name: string): boolean {
return this.headers.has(name)
}
Expand Down

0 comments on commit 2a05f95

Please sign in to comment.