Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

613
Views
Nginx como proxy inverso: ¿Cómo mostrar una página de error personalizada para errores ascendentes, A MENOS QUE la fuente ascendente diga que no?

Tengo una instancia de Nginx ejecutándose como proxy inverso. Cuando el servidor ascendente no responde, envío una página de error personalizada para el código de respuesta 502. Cuando el servidor ascendente envía una página de error, se reenvía al cliente y también me gustaría mostrar una página de error personalizada en ese caso.

Si quisiera reemplazar todas las páginas de error del servidor ascendente, configuraría proxy_intercept_errors on para mostrar una página personalizada en cada una de ellas. Sin embargo, hay casos en los que me gustaría devolver la respuesta real que envió el servidor ascendente: por ejemplo, para puntos finales de API, o si la página de error tiene texto específico legible por el usuario relacionado con el problema.

En la configuración, un solo server está enviando múltiples aplicaciones que están detrás de sus propias configuraciones de proxy y sus propias reglas para reenviar solicitudes, por lo que no puedo especificar esto para cada location , y tiene que funcionar para cualquier URL que coincida con un server

Debido a esto, me gustaría enviar la página de error personalizada, a menos que la aplicación original indique lo contrario. La forma más sencilla de hacerlo sería con un encabezado HTTP personalizado. Hay una pregunta similar sobre cómo hacer esto dependiendo de los encabezados de solicitud . ¿Hay alguna manera de hacer esto dependiendo de los encabezados de respuesta ?

(Parece que alguien más ya tenía esta pregunta y su conclusión fue que era imposible con Nginx simple. Si eso es cierto, estaría interesado en algunas otras ideas sobre cómo resolver esto, posiblemente usando OpenResty como lo hizo esa persona).

Hasta ahora he intentado usar OpenResty para hacer esto, pero no parece compatible con proxy_pass : la respuesta que genera el código Lua parece sobrescribir la respuesta del servidor ascendente.

Aquí está el bloque de location que traté de usar:

 location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost:65000; content_by_lua_block{ ngx.say("This seems to overwrite the content from the proxy?!") } body_filter_by_lua_block { ngx.arg[1]="Truncated by code!" ngx.arg[2]=false if ngx.status >= 400 then if not ngx.resp.get_headers()["X-Verbatim"] then local file = io.open('/usr/share/nginx/error.html', 'w') local html_text = file:read("*a") ngx.arg[1] = html_text ngx.arg[2] = true return end end } }
over 4 years ago · Santiago Trujillo
2 answers
Answer question

0

No creo que pueda enviar páginas de error personalizadas basadas en el encabezado de respuesta, ya que la única forma, según mi conocimiento, podría lograrlo usando el map o la directiva if . Dado que ambas directivas no tienen alcance después de que la solicitud se envía a la parte superior, no es posible que puedan leer el encabezado de respuesta.

Sin embargo, puede hacer esto usando openresty y escribiendo su propio script lua. El script lua para hacer tal cosa se vería así:

 location / { body_filter_by_lua ' if ngx.resp.get_headers()["Cust-Resp-Header"] then local file = io.open('/path/to/file.html', 'r') local html_text = f:read() ngx.arg[1] = html_text ngx.arg[2] = true return end '; # . . . }

También podría usar body_filter_by_lua_block (podría encerrar su código lua dentro de llaves en lugar de escribirlo como una cadena nginx) o body_filter_by_lua_file (podría escribir su código lua en un archivo separado y proporcionar la ruta del archivo).

Puede encontrar cómo comenzar con openresty aquí .

PD: puede leer el código de estado de la respuesta desde arriba usando ngx.status . En lo que respecta a la lectura del cuerpo, la variable ngx.arg[1] contendría el cuerpo de la respuesta después de la respuesta del flujo ascendente que estamos modificando aquí. Puede guardar el ngx.arg[1] en una variable local e intentar leer el mensaje de error usando alguna expresión regular y agregando más tarde en la variable html_text . Espero que ayude.

Edición 1: pegar aquí un bloque lua de trabajo de muestra dentro de un bloque de ubicación con proxy_pass:

 location /hello { proxy_pass http://localhost:3102/; body_filter_by_lua_block { if ngx.resp.get_headers()["erratic"] == "true" then ngx.arg[1] = "<html><body>Hi</body></html>" end } }

Edición 2: no puede usar content_by_lua_block con proxy_pass o, de lo contrario, su proxy no funcionaría. Su bloque de ubicación debería tener este aspecto (suponiendo que el encabezado X-Verbatim esté configurado en "falso" (una cadena) si tiene que anular el cuerpo de la respuesta de error desde arriba).

 location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_pass http://localhost:65000; body_filter_by_lua_block { if ngx.status >= 400 then if ngx.resp.get_headers()["X-Verbatim"] == "false" then local file = io.open('/usr/share/nginx/error.html', 'w') local html_text = file:read("*a") ngx.arg[1] = html_text ngx.arg[2] = true end end }

}

over 4 years ago · Santiago Trujillo Report

0

Esto es algo opuesto a lo solicitado, pero creo que puede encajar de todos modos. Muestra la respuesta original a menos que aguas arriba diga qué mostrar .

Hay un conjunto de encabezados personalizados de X-Accel que se evalúan a partir de las respuestas anteriores. X-Accel-Redirect le permite decirle a NGINX que procese otra ubicación en su lugar. A continuación se muestra un ejemplo de cómo se puede utilizar.

Esta es una aplicación Flask que da 50/50 respuestas y errores normales. Las respuestas de error vienen con el encabezado X-Accel-Redirect , que le indica a NGINX que responda con el contenido de la ubicación @error_page .

 import flask import random application = flask.Flask(__name__) @application.route("/") def main(): if random.randint(0, 1): resp = flask.Response("Random error") # upstream body contents resp.headers['X-Accel-Redirect'] = '@error_page' # the header return resp else: return "Normal response" if __name__ == '__main__': application.run("0.0.0.0", port=4000)

Y aquí hay una configuración de NGINX para eso:

 server { listen 80; location / { proxy_pass http://localhost:4000/; } location @error_page { return 200 "That was an error"; } }

Al juntarlos, verá "Respuesta normal" de la aplicación o "Eso fue un error" de la ubicación @error_page (se suprimirá "Error aleatorio"). Con esta configuración, puede crear varias ubicaciones ( @error_502 , @foo , @etc ) para varios errores y hacer que su aplicación los use.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!