Node js ошибка 403

The issue is that your server is not configured to respond to OPTIONS requests with the correct response status, 2xx success status.

The GET is working because it is not making a preflight request, as it meets the criteria to be a simple request as defined by the CORS documentation

On the other hand, the POST request meets the criteria to be a Preflighted request, meaning a preflight OPTIONS request should be made first.

In short, you have correctly setup the CORS response headers, but the server is not configured to respond with a 2xx response for OPTIONS method requests(commonly 200 status).

The server must respond to OPTIONS requests with a 2xx success status—typically 200 or 204.

If the server doesn’t do that, it makes no difference what Access-Control-* headers you have it configured to send. And the answer to configuring the server to handle OPTIONS requests in the right way—to send a 200 or 204 success message—depends on what server software it’s running

Borrowing the solution from this answer, do this on your backend, .NET WEB API:

In your BaseApiController.cs:

We do this to allow the OPTIONS http verb

public class BaseApiController : ApiController
  {
    public HttpResponseMessage Options()
    {
      return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
    }
}

References

Preflighted requests

response for preflight 403 forbidden

Note

Running a nodejs server on domainA.com is irrelevent. The «axios» library can be used either to a) make XMLHttpRequests from the browser or b) make http requests from node.js. In this case it is the first option, the «axios.post» to domainB is done through a XMLHttpRequest from the browser, that `s why you get a preflighted request at domainB.com.

Когда я только начинал работать с Express и пытался разобраться с тем, как обрабатывать ошибки, мне пришлось нелегко. Возникало такое ощущение, будто никто не писал о том, что мне было нужно. В итоге мне пришлось самому искать ответы на мои вопросы. Сегодня я хочу рассказать всё, что знаю об обработке ошибок в Express-приложениях. Начнём с синхронных ошибок.

Обработка синхронных ошибок

Если вам нужно обработать синхронную ошибку, то вы можете, для начала, с помощью инструкции throw, выдать такую ошибку в обработчике запроса Express. Обратите внимание на то, что обработчики запросов ещё называют «контроллерами», но я предпочитаю использовать термин «обработчик запросов» так как он кажется мне понятнее.

Вот как это выглядит:

app.post('/testing', (req, res) => {
  throw new Error('Something broke! ')
})

Такие ошибки можно перехватить с помощью обработчика ошибок Express. Если вы не написали собственный обработчик ошибок (подробнее об этом мы поговорим ниже), то Express обработает ошибку с помощью обработчика, используемого по умолчанию.

Вот что делает стандартный обработчик ошибок Express:

  1. Устанавливает код состояния HTTP-ответа в значение 500.
  2. Отправляет сущности, выполнившей запрос, текстовый ответ.
  3. Логирует текстовый ответ в консоль.

Сообщение об ошибке, выведенное в консоль

Обработка асинхронных ошибок

Для обработки асинхронных ошибок нужно отправить ошибку обработчику ошибок Express через аргумент next:

app.post('/testing', async (req, res, next) => {
  return next(new Error('Something broke again! '))
})

Вот что попадёт в консоль при логировании этой ошибки.

Сообщение об ошибке, выведенное в консоль

Если вы пользуетесь в Express-приложении конструкцией async/await, то вам понадобится использовать функцию-обёртку, наподобие express-async-handler. Это позволяет писать асинхронный код без блоков try/catch. Подробнее об async/await в Express можно почитать здесь.

const asyncHandler = require('express-async-handler')

app.post('/testing', asyncHandler(async (req, res, next) => {
  // Сделать что-нибудь
}))

После того, как обработчик запроса обёрнут в express-async-handler, то можно, так же, как было описано выше, выбросить ошибку с использованием инструкции throw. Эта ошибка попадёт к обработчику ошибок Express.

app.post('/testing', asyncHandler(async (req, res, next) => {
  throw new Error('Something broke yet again! ')
}))

Сообщение об ошибке, выведенное в консоль

Написание собственного обработчика ошибок

Обработчики ошибок Express принимают 4 аргумента:

  1. error
  2. req
  3. res
  4. next

Размещать их нужно после промежуточных обработчиков и маршрутов.

app.use(/*...*/)
app.get(/*...*/)
app.post(/*...*/)
app.put(/*...*/)
app.delete(/*...*/)

// Собственный обработчик ошибок нужно поместить после всех остальных промежуточных обработчиков
app.use((error, req, res, next) => { /* ... */ })

Если создать собственный обработчик ошибок, то Express прекратит использование стандартного обработчика. Для того чтобы обработать ошибку, нужно сформировать ответ для фронтенд-приложения, которое обратилось к конечной точке, в которой возникла ошибка. Это означает, что нужно выполнить следующие действия:

  1. Сформировать и отправить подходящий код состояния ответа.
  2. Сформировать и отправить подходящий ответ.

То, какой именно код состояния подойдёт в каждом конкретном случае, зависит от того, что именно произошло. Вот список типичных ошибок, к обработке которых вы должны быть готовы:

  1. Ошибка 400 Bad Request. Используется в двух ситуациях. Во-первых — тогда, когда пользователь не включил в запрос необходимое поле (например — в отправленной платёжной форме не заполнено поле со сведениями о кредитной карте). Во-вторых — тогда, когда в запросе содержатся некорректные данные (например — ввод в поле пароля и в поле подтверждения пароля разных паролей).
  2. Ошибка 401 Unauthorized. Этот код состояния ответа применяется в том случае, если пользователь ввёл неправильные учётные данные (вроде имени пользователя, адреса электронной почты или пароля).
  3. Ошибка 403 Forbidden. Используется в тех случаях, когда пользователю не разрешён доступ к конечной точке.
  4. Ошибка 404 Not Found. Применяется в тех случаях, когда конечную точку невозможно обнаружить.
  5. Ошибка 500 Internal Server Error. Применяется тогда, когда запрос, отправленный фронтендом, сформирован правильно, но на бэкенде при этом возникла какая-то ошибка.

После того, как определён подходящий код состояния ответа, его нужно установить с помощью res.status:

app.use((error, req, res, next) => {
  // Ошибка, выдаваемая в ответ на неправильно сформированный запрос
  res.status(400)
  res.json(/* ... */)
})

Код состояния ответа должен соответствовать сообщению об ошибке. Для этого нужно отправлять код состояния вместе с ошибкой.

Легче всего это сделать с помощью пакета http-errors. Он позволяет отправлять в ошибке три фрагмента информации:

  1. Код состояния ответа.
  2. Сообщение, сопутствующее ошибке.
  3. Любые данные, которые нужно отправить (это необязательно).

Вот как установить пакет http-errors:

npm install http-errors --save

Вот как этим пакетом пользоваться:

const createError = require('http-errors')

// Создание ошибки
throw createError(status, message, properties)

Рассмотрим пример, который позволит как следует в этом всём разобраться.

Представим, что мы пытаемся обнаружить пользователя по адресу его электронной почты. Но этого пользователя найти не удаётся. В результате мы решаем отправить в ответ на соответствующий запрос ошибку User not found, сообщающую вызывающей стороне о том, что пользователь не найден.

Вот что нам нужно будет сделать при создании ошибки:

  1. Установить код состояния ответа как 400 Bad Request (ведь пользователь ввёл неправильные данные). Это будет наш первый параметр.
  2. Отправить вызывающей стороне сообщение наподобие User not found. Это будет второй параметр.

app.put('/testing', asyncHandler(async (req, res) => {
  const { email } = req.body
  const user = await User.findOne({ email })

  // Если пользователь не найден - выбросим ошибку
  if (!user) throw createError(400, `User '${email}' not found`)
}))

Получить код состояния можно с помощью конструкции error.status, а сообщение ошибки — с помощью error.message:

// Логирование ошибки
app.use((error, req, res, next) => {
  console.log('Error status: ', error.status)
  console.log('Message: ', error.message)
})

Результат логирования ошибки в консоли

Затем состояние ответа устанавливают с помощью res.status, а сообщение записывают в res.json:

app.use((error, req, res, next) => {
  // Установка кода состояния ответа
  res.status(error.status)

  // Отправка ответа
  res.json({ message: error.message })
})

Лично я предпочитаю отправлять в подобных ответах код состояния, сообщение и результат трассировки стека. Это облегчает отладку.

app.use((error, req, res, next) => {
  // Установка кода состояния ответа
  res.status(error.status)

  // Отправка ответа
  res.json({
    status: error.status,
    message: error.message,
    stack: error.stack
  })
})

▍Код состояния ответа, используемый по умолчанию

Если источником ошибки не является createError, то у неё не будет свойства status. Вот пример, в котором сделана попытка прочесть несуществующий файл с помощью fs.readFile:

const fs = require('fs')
const util = require('util')

// Преобразуем readFile из функции, использующей коллбэки, в async/await-функцию.
// Подробности об этом смотрите здесь: https://zellwk.com/blog/callbacks-to-promises
const readFilePromise = util.promisify(fs.readFile)

app.get('/testing', asyncHandler(async (req, res, next) => {
  const data = await readFilePromise('some-file')
})

У такого объекта ошибки не будет свойства status:

app.use((error, req, res, next) => {
  console.log('Error status: ', error.status)
  console.log('Message: ', error.message)
})

Результат логирования ошибки в консоли

В подобных случаях можно задать код ошибки, используемый по умолчанию. А именно, речь идёт об ошибке 500 Internal Server Error:

app.use((error, req, res, next) => {
  res.status(error.status || 500)
  res.json({
    status: error.status,
    message: error.message,
    stack: error.stack
  })
})

▍Изменение кода состояния ошибки

Предположим, мы собираемся прочитать некий файл, воспользовавшись данными, предоставленными пользователем. Если такого файла не существует, это значит, что нам нужно выдать ошибку 400 Bad Request. Ведь в том, что файл найти не удаётся, нет вины сервера.

В подобном случае нужно воспользоваться конструкцией try/catch для перехвата исходной ошибки. Затем нужно воссоздать объект ошибки с помощью createError:

app.get('/testing', asyncHandler(async (req, res, next) => {
  try {
    const { file } = req.body
    const contents = await readFilePromise(path.join(__dirname, file))
  } catch (error) {
    throw createError(400, `File ${file} does not exist`)
  }
})

▍Обработка ошибок 404

Если запрос прошёл через все промежуточные обработчики и маршруты, но так и не был обработан, это означает, что конечная точка, соответствующая такому запросу, не была найдена.

Для обработки ошибок 404 Not Found нужно добавить, между маршрутами и обработчиком ошибок, дополнительный обработчик. Вот как выглядит создание объекта ошибки 404:

// Промежуточные обработчики...
// Маршруты...

app.use((req, res, next) => {
  next(createError(404))
})

// Обработчик ошибок...

Сведения об ошибке

▍Замечания об ошибке ERR_HTTP_HEADERS_SENT

Не впадайте в панику если видите сообщение об ошибке ERR_HTTP_HEADERS_SENT: Cannot set headers after they are sent to the client. Она возникает из-за того, что в одном и том же обработчике многократно вызывается метод, устанавливающий заголовки ответа. Вот методы, вызов которых приводит к автоматической установке заголовков ответа:

  1. res.send
  2. res.json
  3. res.render
  4. res.sendFile
  5. res.sendStatus
  6. res.end
  7. res.redirect

Так, например, если вы вызовете методы res.render и res.json в одном и том же обработчике ответа, то вы получите ошибку ERR_HTTP_HEADERS_SENT:

app.get('/testing', (req, res) => {
  res.render('new-page')
  res.json({ message: '¯_(ツ)_/¯' })
})

В результате, в том случае, если вы сталкиваетесь с этой ошибкой, тщательно проверьте код обработчиков ответа и убедитесь в том, что в нём нет ситуаций, в которых вызывается несколько вышеописанных методов.

▍Обработка ошибок и потоковая передача данных

Если что-то идёт не так при потоковой передаче ответа фронтенду, то можно столкнуться с той же самой ошибкой ERR_HTTP_HEADERS_SENT.

В подобном случае обработку ошибок нужно передать стандартным обработчикам. Такой обработчик отправит ошибку и автоматически закроет соединение.

app.use((error, req, res, next) => {
  // Сделать это нужно только в том случае, если ответ передаётся в потоковом режиме
  if (res.headersSent) {
    return next(error)
  }

  // Остальной код обработки ошибок
})

Итоги

Сегодня я рассказал вам всё, что знаю об обработке ошибок в Express. Надеюсь, это поможет вам писать более надёжные Express-приложения.

Уважаемые читатели! Как вы обрабатываете ошибки в своих Node.js-проектах?

I was trying to install some modules in Nodejs, using NPM, but in some cases the install dont go on, and a error is returned:

Error: 403 status code downloading tarball

I got this again when I trying to install node-canvas:

D:servernode_modulescanvasnode_modulescanvas>node "C:Program Filesnodejsnode_modulesnpmbinnode-gyp-bin\....node_modulesnode-gypbinnode-gyp.js" rebuild
gyp http GET http://nodejs.org/dist/v0.8.3/node-v0.8.3.tar.gz
gyp http 403 http://nodejs.org/dist/v0.8.3/node-v0.8.3.tar.gz
gyp WARN install got an error, rolling back install
gyp ERR! rebuild error Error: 403 status code downloading tarball
gyp ERR! rebuild error     at Request.async (C:Program Filesnodejsnode_modulesnpmnode_modulesnode-gyplibinstall.js:215:14)
gyp ERR! rebuild error     at Request.EventEmitter.emit (events.js:115:20)
gyp ERR! rebuild error     at ClientRequest.<anonymous> (C:Program Filesnodejsnode_modulesnpmnode_modulesrequestmain.js:521:12)
gyp ERR! rebuild error     at ClientRequest.g (events.js:185:14)
gyp ERR! rebuild error     at ClientRequest.EventEmitter.emit (events.js:88:17)
gyp ERR! rebuild error     at HTTPParser.parserOnIncomingClient (http.js:1445:7)
gyp ERR! rebuild error     at HTTPParser.parserOnHeadersComplete [as onHeadersComplete] (http.js:111:23)
gyp ERR! rebuild error     at Socket.socketOnData (http.js:1356:20)
gyp ERR! rebuild error     at TCP.onread (net.js:404:27)
gyp ERR! not ok
canvas@1.0.2 node_modulescanvas

I’m using Windows 7 64x
Nodejs 0.8.3

what could be this error?
What is ‘tarball’?

  • Remove From My Forums
  • Question

  • I’ve created a React Web Starter Kit project which runs successfully on my local Windows 10 box.  I have followed

    directions to publish my web app to Azure.  I also followed directions to have

    Azure’s Kudu run a custom script for installing and building my app.

    The custom deployment works correctly but I cannot access my site.  I receive a 403 when I try to browse http://axiscode.azurewebsites.com.  Could it be that my site was correctly built, but Azure/Kudu did not bother to execute «node server.js»?

    The custom deployment output looks like this:

    remote: Preparing deployment for commit id '058581114c'.
    remote: Running custom deployment command...
    remote: Running deployment command...
    remote:
    remote: D:homesiterepository>call npm install
    remote: ...............................
    remote: D:homesiterepository
    remote: npm WARN optional Skipping failed optional dependency /chokidar/fsevents:
    remote: +-- babel@5.8.34
    remote: npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.6
    remote: ¦ +-- glob@5.0.15
    remote: npm WARN optional Skipping failed optional dependency /browser-sync/chokidar/fsevents:
    remote: +-- babel-core@5.8.34
    remote: npm WARN notsup Not compatible with your operating system or architecture: fsevents@1.0.6
    remote: ¦ +-- regenerator@0.8.40
    remote: ¦   +-- commoner@0.10.4
    remote: ¦     +-- glob@5.0.15
    remote: +-- eslint@1.10.3
    remote: ¦ +-- glob@5.0.15
    remote: +-- jest-cli@0.8.2
    remote: ¦ +-- istanbul@0.3.22
    remote: ¦   +-- fileset@0.2.1
    remote: ¦     +-- glob@5.0.15
    remote: +-- jscs@2.8.0
    remote: ¦ +-- glob@5.0.15
    remote: +-- postcss-import@7.1.3
    remote: ¦ +-- glob@5.0.15
    remote: +-- precss@1.4.0
    remote:   +-- postcss-mixins@2.1.1
    remote:     +-- globby@3.0.1
    remote:       +-- glob@5.0.15
    remote:
    remote:
    remote: > @ build D:homesiterepository
    remote: > babel-node tools/run build
    remote:
    remote: ...................
    remote: [06:40:25] Starting 'build'...
    remote: [06:40:25] Starting 'clean'...
    remote: [06:40:25] Finished 'clean' after 31 ms
    remote: [06:40:25] Starting 'copy'...
    remote: build/package.json
    remote: [06:40:25] Finished 'copy' after 234 ms
    remote: [06:40:25] Starting 'bundle'...
    remote: .....................
    remote: Child
    remote:     Time: 24924ms
    remote:                            Asset     Size  Chunks             Chunk Names
    remote:     main.js?e1ad0f66932a7e39e0b4  2.85 MB       0  [emitted]  main
    remote: Child
    remote:     Time: 24236ms
    remote:             Asset    Size  Chunks             Chunk Names
    remote:         server.js  204 kB       0  [emitted]  main
    remote:     server.js.map  186 kB       0  [emitted]  main
    remote: [06:40:51] Finished 'bundle' after 25924 ms
    remote: [06:40:51] Finished 'build' after 26189 ms
    remote: ..........................................................................................................................................
    remote: D:homesiterepositorybuildassets.js
    remote: D:homesiterepositorybuildpackage.json
    remote: D:homesiterepositorybuildserver.js
    remote: D:homesiterepositorybuildserver.js.map
    remote: D:homesiterepositorybuildcontentabout.jade
    remote: D:homesiterepositorybuildcontentindex.jade
    remote: D:homesiterepositorybuildcontentprivacy.jade
    remote: D:homesiterepositorybuildpublicapple-touch-icon.png
    remote: D:homesiterepositorybuildpublicbrowserconfig.xml
    remote: D:homesiterepositorybuildpubliccrossdomain.xml
    remote: D:homesiterepositorybuildpublicfavicon.ico
    remote: D:homesiterepositorybuildpublichumans.txt
    remote: D:homesiterepositorybuildpublicmain.js
    remote: D:homesiterepositorybuildpublicrobots.txt
    remote: D:homesiterepositorybuildpublictile-wide.png
    remote: D:homesiterepositorybuildpublictile.png
    remote: 16 File(s) copied
    remote: Custom build finished successfully.
    remote: Running post deployment command(s)...
    remote: Deployment successful.
    To https://Mystagogue@axiscode.scm.azurewebsites.net:443/AxisCode.git
       22fbf15..0585811  master -> master

    -Brent Arias

    • Edited by

      Friday, July 1, 2016 2:16 AM
      update title

    • Moved by
      Jambor yaoMicrosoft employee
      Friday, July 1, 2016 2:16 AM

Answers

  • As the introduction at
    How to Build, Test, Deploy of the react-starter-kit Getting Started guide, I followed it and configure a few custom configurations on Azure, it works fine on my side, here are my steps for your information:

    1. clone the project repo at https://github.com/kriasoft/react-starter-kit to local,  and deploy it to Azure Web app via GI, you can refer to Continuous
      deployment using GIT in Azure App Service
    2. login Azure mange portal, enabled EDIT IN VISUAL STUDIO ONLINE
      under CONFIGURE tab, then I can leverage VSO to modify the code on Azure online. 
    3. click the edit in VSO under the DASHBOARD of your manage portal site, click the «open console» at left nav on VSO.
    4. run following commands: 
    npm update
    npm run build
    1. create a file named `web.config` at the root directory of your site, with the following content:
    <configuration>
      <system.webServer>
    
        <handlers>
          <!-- indicates that the app.js file is a node.js application to be handled by the iisnode module -->
          <add name="iisnode" path="build/server.js" verb="*" modules="iisnode" />
        </handlers>
    
        <rewrite>
          <rules>        
    
            <!-- All other URLs are mapped to the Node.js application entry point -->
            <rule name="DynamicContent">
              <conditions>
                <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="True" />
              </conditions>
              <action type="Rewrite" url="build/server.js" />
            </rule>
          </rules>
        </rewrite>
      </system.webServer>
    </configuration>
    

    After all, click «Run» button at left nav to have a test view.

    Any concern, please feel free to let me know.

    • Marked as answer by
      Brent Arias
      Monday, January 18, 2016 6:15 PM

Describe the issue

I want to crawling information of place (api)
(url : http://store.naver.com/sogum/api/businesses?start=1&display=20&query=%EC%8B%A4%EB%82%B4%EB%86%80%EC%9D%B4%ED%84%B0)

When i did in local, it runs well. I got json.
But on ubuntu(ec2) it is not working.

Example Code

const axios = require(‘axios’)
const request = require(‘request’)

axios.get(http://store.naver.com/sogum/api/businesses?start=1&display=20&query=%EC%8B%A4%EB%82%B4%EB%86%80%EC%9D%B4%ED%84%B0)
.then(data => {
console.log(‘data : ‘, data)
})

Expected behavior, if applicable

[nodemon] starting node crawling.js
(node:5088) UnhandledPromiseRejectionWarning: Error: Request failed with status code 403
at createError (/home/ubuntu/internship_project/project/node_modules/axios/lib/core/createError.js:16:15)
at settle (/home/ubuntu/internship_project/project/node_modules/axios/lib/core/settle.js:17:12)
at IncomingMessage.handleStreamEnd (/home/ubuntu/internship_project/project/node_modules/axios/lib/adapters/http.js:236:11)
at IncomingMessage.emit (events.js:327:22)
at endReadableNT (_stream_readable.js:1220:12)
at processTicksAndRejections (internal/process/task_queues.js:84:21)
(node:5088) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag —unhandled-rejections=strict (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)
(node:5088) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
[nodemon] clean exit — waiting for changes before restart

Environment

  • Axios Version ^0.19.2
  • Node.js Version 12LTS
  • OS: aws ec2 ubuntu 16.04

Additional context/Screenshots

I want to know why it is not working, and if in virtual os, can’t i crawling information?
Thank you!

Понравилась статья? Поделить с друзьями:
  • Node is not defined ошибка
  • Nod32 при установке драйвера edevmon произошла ошибка
  • Nod32 ошибка при удалении
  • Not a statement java ошибка что значит
  • Not a legal oleaut date ошибка