У меня есть приложение React, созданное Create-React-app и Redux вместе с бэкэндом Node.js (в частности, Express.js). В файле внешнего интерфейса package.json я установил «прокси: http://localhost:5000», чтобы перенаправить все вызовы API из приложения реагирования на внутренний сервер. Тем временем внутренний сервер одновременно работает и прослушивает порт localhost: 5000.
Структура приложения показана ниже: Структура приложения
Файл package.json в папке клиента (интерфейс) настраивает прокси следующим образом.
{
...,
"proxy": "http://localhost:5000"
}
В App.js (точка входа во внешний интерфейс) я создал несколько URL-маршрутов с помощью реакции-маршрутизатора-dom:
return (
<ThemeProvider theme = {theme}>
<Provider store = {store}>
<Fragment>
<Router>
<div
className='App'
style = {{ fontFamily: 'Montserrat', fontWeight: '500' }}>
<header>
<Navbar />{' '}
</header>
<div>
<Routes>
<Route exact path='/' element = {<Home />} />
<Route exact path='/home' element = {<Home />} />
<Route exact path='/dashboard' element = {<Dashboard />} />
<Route exact path='/about' element = {<About />} />
<Route exact path='/register' element = {<Register />} />
<Route exact path='/login' element = {<Login />} />
<Route exact path='/forgot' element = {<ForgotPassword />} />
<Route path='/reset' element = {<ResetPassword />} />
<Route path='/avatar' element = {<ChangeAvatar />} />
<Route
exact
path='/systemtables'
element = {<SystemTables />}
/>
<Route exact path='/profiles' element = {<ProfileMain />} />
<Route exact path='/companies' element = {<CompanyMain />} />
...
</Routes>
</div>
</div>
</Router>
</Fragment>
</Provider>
</ThemeProvider>
);
Файл package.json в корне приложения (папка AAQCS) выглядит следующим образом:
{
...,
"scripts": {
"start": "node index.js",
"server": "nodemon index.js --ignore temp/",
"client": "npm start --prefix client",
"clientinstall": "npm install -prefix client",
"dev": "concurrently \"npm run server\" \"npm run client\""
},
"devDependencies": {
"concurrently": "^6.0.2",
"nodemon": "^2.0.19"
}
}
В «web-server.js» (точка входа в серверную часть) у меня есть код ниже:
const app = express();
app.use(cors());
httpServer = http.createServer(app);
//Set server side static uploads folder receiving front-end upload request.
app.use('/public', express.static('public'));
// Combines logging info from request and response
app.use(morgan('combined'));
//Init Middleware to receive request body
app.use(express.json({ extended: false, limit: '50000mb' }));
app.use(favicon(__dirname + '/images/favicon.ico'));
//Serve any static files built by React
app.use(express.static(path.join(__dirname, 'client/build')));
app.get('/', function (req, res) {
res.sendFile(path.join(__dirname, 'client/build', 'index.html'));
});
//Define Routes
app.use('/api/users', require('./routes/users'));
app.use('/api/auth', require('./routes/auth'));
app.use('/api/asset', require('./routes/asset'));
app.use('/api/companies', require('./routes/companies'));
...
httpServer
.listen(webServerConfig.port)
.on('listening', () => {
console.info(
`Web server listening on localhost:${webServerConfig.port}`
);
resolve();
})
.on('error', (err) => {
reject(err);
});
Внутренний сервер прослушивает локальный хост: 5000.
В настоящее время у меня есть эти правила в файле web.config:
<rules>
<clear />
<rule name = "RedirectToBackend" stopProcessing = "true">
<match url = "^api/(.*)" />
<conditions logicalGrouping = "MatchAll" trackAllCaptures = "false" />
<action type = "Redirect" url = "http://localhost:5000/api/{R:1}" />
</rule>
<rule name = "React Routes" stopProcessing = "true">
<match url = ".*" />
<conditions logicalGrouping = "MatchAll" trackAllCaptures = "true">
<add input = "{REQUEST_FILENAME}" matchType = "IsFile" negate = "true" />
<add input = "{REQUEST_FILENAME}" matchType = "IsDirectory" negate = "true" />
<add input = "{REQUEST_URI}" pattern = "^api/(.*)" negate = "true" />
</conditions>
<action type = "Redirect" url = "{R:0}" />
</rule>
</rules>
Когда я нахожусь в среде разработки, все работает, все маршруты работают.
После того, как я поместил сборку в IIS, я могу запустить страницу входа, но когда я нажимаю кнопку «Вход», я получаю ошибку: «POST http://localhost:3000/api/auth
500 (ошибка модуля перезаписи URL-адреса.)»
Мои вопросы:
Поэтому я изменил тип на Rewrite и установил ARR, как предложил @Yurong Dai. Теперь я успешно вошел в систему, но не все маршруты реагирования работают, хотя я настроил маршруты точно так же в App.js.
Вам необходимо установить ARR и включить функцию прокси-сервера для работы с IIS в качестве обратного прокси-сервера, который может перенаправлять все вызовы API в формате «/api/xxxx» на внутренний сервер NodeJS.
Убедитесь, что для типа действия перезаписи URL-адреса установлено значение «Перезапись», а не «Перенаправление», поскольку вы хотите передать запрос через прокси, а не выполнять перенаправление.
<rule name = "RedirectToBackend" stopProcessing = "true">
<match url = "^api/(.*)" />
<action type = "Rewrite" url = "http://localhost:5000/api/{R:1}" />
</rule>
Кроме того, все остальные запросы без формата «/api/xxxx» должны следовать маршруту, установленному в приложении React. Вам необходимо создать следующее правило, которое будет перезаписывать все запросы, не относящиеся к API, на корневой URL-адрес («/»), где их будет обрабатывать маршрутизация приложения React.
<rule name = "React Routes" stopProcessing = "true">
<match url = ".*" />
<conditions logicalGrouping = "MatchAll" trackAllCaptures = "true">
<add input = "{REQUEST_FILENAME}" matchType = "IsFile" negate = "true" />
<add input = "{REQUEST_FILENAME}" matchType = "IsDirectory" negate = "true" />
<add input = "{REQUEST_URI}" pattern = "^/api/(.*)" negate = "true" />
</conditions>
<action type = "Rewrite" url = "/" />
</rule>
Спасибо за подробное решение. Я вошел в систему правильно. Я также правильно обработал большую часть вызовов, не связанных с API, с помощью ваших правил, приведенных выше, за исключением некоторых маршрутизаций, когда я нажимал кнопку, например: сервер выдал мне сообщение Cannot GET /assessmentaudits. У меня была точно такая же настройка маршрутизации в App.js, как и в других, таких как /login, /register и т. д. Нужно ли мне специально прописывать этот URL в правилах?
Однако с вышеуказанной ошибкой есть еще кое-что: когда я навожу курсор на кнопку, запускающую компонент assessmentaudits
, в левом нижнем углу экрана отображается ссылка http://localhost:3000/assessmentaudits
. Но когда я нажал кнопку, URL-адрес в браузере фактически превратился в http://localhost:5000/assessmentaudits
, что и вызвало вышеуказанную ошибку. Что я сделал не так? Ценю вашу помощь.
Настроили ли вы маршрут /assesmentaudits, соответствующий компоненту Assessmentaudits в App.js? Создали ли вы какие-либо другие правила помимо правил перезаписи в ответе выше?
Я предлагаю вам попробовать использовать FRT для отслеживания запроса, вы увидите, как правила используются внутри. Learn.microsoft.com/en-us/iis/extensions/url-rewrite-module/…
Спасибо за ваш быстрый ответ. Да, у меня был этот код в App.js: <Route exact path='/assessmentaudits' element = {<AssessmentAudits />} />
. Я вспомнил, что когда я проверял «Включить прокси в ARR», я также проверял «Использовать перезапись URL-адреса» для проверки входящих запросов в разделе «Тип прокси» и ставил localhost:5000
в поле «Обратный прокси». Увидев ваш ответ, я снял флажок «Использовать перезапись URL-адреса», чтобы проверить входящие запросы и применить изменения. Оставит ли это «другое правило» в системе? Завтра я обязательно рассмотрю ваше предложение по отслеживанию FRT и сообщу вам результат.
Решена проблема, когда я изменил URL-адрес «/assessmentaudits» на «/asmtaudits» в маршрутизациях React в App.js. Не знаю, почему это произошло. Возможно, этот URL-адрес случайно совпадал с первым уровнем нашего домена, который называется «assessmentaudit.ma....» (как такое могло случиться, даже если доменное имя не заканчивается на «s»). Огромное спасибо за помощь, ЮронгДай. Ты мужчина!!!
<action type = "Redirect" url = "http://localhost:5000/api/{R:1}" />
недействителен. Вы не можете просто перенаправить туда браузеры (этот URL-адрес недействителен на компьютерах со стороны браузера), и вам необходимо настроить полный обратный прокси-сервер.