diff --git a/fixtures/flight/package.json b/fixtures/flight/package.json
index 680c1a0055220..9e0906f0b3ea1 100644
--- a/fixtures/flight/package.json
+++ b/fixtures/flight/package.json
@@ -16,6 +16,7 @@
"babel-plugin-named-asset-import": "^0.3.8",
"babel-preset-react-app": "^10.0.1",
"bfj": "^7.0.2",
+ "body-parser": "^1.20.1",
"browserslist": "^4.18.1",
"camelcase": "^6.2.1",
"case-sensitive-paths-webpack-plugin": "^2.4.0",
diff --git a/fixtures/flight/server/cli.js b/fixtures/flight/server/cli.js
index 0705d824dfc08..dea40db72ee59 100644
--- a/fixtures/flight/server/cli.js
+++ b/fixtures/flight/server/cli.js
@@ -25,6 +25,7 @@ babelRegister({
});
const express = require('express');
+const bodyParser = require('body-parser');
const app = express();
// Application
@@ -32,6 +33,17 @@ app.get('/', function (req, res) {
require('./handler.js')(req, res);
});
+app.options('/', function (req, res) {
+ res.setHeader('Allow', 'Allow: GET,HEAD,POST');
+ res.setHeader('Access-Control-Allow-Origin', '*');
+ res.setHeader('Access-Control-Allow-Headers', 'rsc-action');
+ res.end();
+});
+
+app.post('/', bodyParser.text(), function (req, res) {
+ require('./handler.js')(req, res);
+});
+
app.get('/todos', function (req, res) {
res.setHeader('Access-Control-Allow-Origin', '*');
res.json([
diff --git a/fixtures/flight/server/handler.js b/fixtures/flight/server/handler.js
index 5b6f6b2abea8b..549424afaf525 100644
--- a/fixtures/flight/server/handler.js
+++ b/fixtures/flight/server/handler.js
@@ -1,31 +1,49 @@
'use strict';
const {renderToPipeableStream} = require('react-server-dom-webpack/server');
-const {readFile} = require('fs');
+const {readFile} = require('fs').promises;
const {resolve} = require('path');
const React = require('react');
-module.exports = function (req, res) {
- // const m = require('../src/App.js');
- import('../src/App.js').then(m => {
- const dist = process.env.NODE_ENV === 'development' ? 'dist' : 'build';
- readFile(
- resolve(__dirname, `../${dist}/react-client-manifest.json`),
- 'utf8',
- (err, data) => {
- if (err) {
- throw err;
- }
-
- const App = m.default.default || m.default;
- res.setHeader('Access-Control-Allow-Origin', '*');
- const moduleMap = JSON.parse(data);
- const {pipe} = renderToPipeableStream(
- React.createElement(App),
- moduleMap
- );
- pipe(res);
+module.exports = async function (req, res) {
+ switch (req.method) {
+ case 'POST': {
+ const serverReference = JSON.parse(req.get('rsc-action'));
+ const {filepath, name} = serverReference;
+ const action = (await import(filepath))[name];
+ // Validate that this is actually a function we intended to expose and
+ // not the client trying to invoke arbitrary functions. In a real app,
+ // you'd have a manifest verifying this before even importing it.
+ if (action.$$typeof !== Symbol.for('react.server.reference')) {
+ throw new Error('Invalid action');
}
- );
- });
+
+ const args = JSON.parse(req.body);
+ const result = action.apply(null, args);
+
+ res.setHeader('Access-Control-Allow-Origin', '*');
+ const {pipe} = renderToPipeableStream(result, {});
+ pipe(res);
+
+ return;
+ }
+ default: {
+ // const m = require('../src/App.js');
+ const m = await import('../src/App.js');
+ const dist = process.env.NODE_ENV === 'development' ? 'dist' : 'build';
+ const data = await readFile(
+ resolve(__dirname, `../${dist}/react-client-manifest.json`),
+ 'utf8'
+ );
+ const App = m.default.default || m.default;
+ res.setHeader('Access-Control-Allow-Origin', '*');
+ const moduleMap = JSON.parse(data);
+ const {pipe} = renderToPipeableStream(
+ React.createElement(App),
+ moduleMap
+ );
+ pipe(res);
+ return;
+ }
+ }
};
diff --git a/fixtures/flight/src/App.js b/fixtures/flight/src/App.js
index 0f86f7edad3cd..91583dd43e79a 100644
--- a/fixtures/flight/src/App.js
+++ b/fixtures/flight/src/App.js
@@ -6,6 +6,9 @@ import {Counter} from './Counter.js';
import {Counter as Counter2} from './Counter2.js';
import ShowMore from './ShowMore.js';
+import Button from './Button.js';
+
+import {like} from './actions.js';
export default async function App() {
const res = await fetch('http://localhost:3001/todos');
@@ -23,6 +26,9 @@ export default async function App() {
Lorem ipsum