H2o: خطأ في H2O.next.call (env)

تم إنشاؤها على ٢٠ يناير ٢٠٢٠  ·  7تعليقات  ·  مصدر: h2o/h2o

أعدت صياغة هذه المشكلة كتقرير "خطأ" ، لأنني الآن اختبرتها أيضًا في ظل Fedora مع أحدث المصادر.

لتوضيح هذا الخطأ ، يمكنك استخدام هذا h2o.conf:

user: www
access-log: /var/log/h2o/h2o-access.log
error-log: /var/log/h2o/h2o-error.log
listen: 8080
hosts:
  "<my-ip-address-here>:8080":
    paths:
      "/dir0":
        mruby.handler: |
          proc {|env|
            resp = H2O.next.call(env)
            resp
          }
        proxy.reverse.url: "https://www.google.com" # this URL is just for testing/demonstration
      "/dir1":
        file.dir: "/usr/local/www/data/testh2o/dir1"
      "/dir2":
        file.dir: "/usr/local/www/data/testh2o/dir2"
      "/":
        file.dir: "/usr/local/www/data/testh2o"

يعمل هذا: يمكنني الوصول إلى الملفات الموجودة ضمن dir1 و dir2 و dir3. وعندما أطلب http://<my-ip-address-here>:8080/dir0 أحصل على صفحة Google الرئيسية (للعرض التوضيحي فقط).

لكن إضافة مقطع واحد إضافي /path يكسر H20.next.call (env) كما هو موصوف هنا لـ HardenedBSD، FreeBSD.

h2o.conf مكسور:

user: www
access-log: /var/log/h2o/h2o-access.log
error-log: /var/log/h2o/h2o-error.log
listen: 8080
hosts:
  "<my-ip-address-here>:8080":
    paths:
      "/dir0":
        mruby.handler: |
          proc {|env|
            resp = H2O.next.call(env)
            # In my production conf I have here code to look for a certain header field.
            # If it finds it, this handler makes a http_request() to a certain URL on another server 
            # in order to trigger emptying a cache. 
            # This bug demo is independent of this code.
            resp
          }
        proxy.reverse.url: "https://www.google.com" # this URL is just for testing/demonstration
      "/dir1":
        file.dir: "/usr/local/www/data/testh2o/dir1"
      "/dir2":
        file.dir: "/usr/local/www/data/testh2o/dir2"
      "/dir3":
        file.dir: "/usr/local/www/data/testh2o/dir3"
      "/":
        file.dir: "/usr/local/www/data/testh2o"

أحصل الآن على خطأ خادم داخلي. ويقول سجل الأخطاء في Fedora:

[h2o_mruby] in request:/dir0:mruby raised: (eval):28: can't modify `SCRIPT_NAME` with `H2O.next`. Is `H2O.reprocess` what you want? (RuntimeError)

هذا في Fedora 31 جديد ، مع H2O مبني من المصدر في b9989220bea9bda30f69083b66166c4c657bdf84 .

ال 7 كومينتر

نظرًا لأن رسالة الخطأ اقترحت باستخدام H2O.reprocess جربت هذا الخيار الآن. نفس النتيجة: إضافة المزيد من المسار-مقاطع تعطل h2o.

hosts:
  test.local:
    listen:
      port: 80
      host: 10.0.0.10
    paths:
      "/dir0":
        file.dir: "/usr/local/www/data/testh2o/dir0"
      "/dir1":
        file.dir: "/usr/local/www/data/testh2o/dir1"
      "/wp-admin":
        mruby.handler: |
          proc {|env|
            env['SCRIPT_NAME'] = '/proxy-wp-admin'
            resp = H2O.reprocess.call(env)
            resp
          }
      "/proxy-wp-admin":
        proxy.reverse.url: "https://www.google.com"

مع فتح هذا التكوين http://test.local/wp-admin في المتصفح يعطيني صفحة Google الرئيسية.

لكن إضافة مقطع مسار آخر ، على سبيل المثال /dir2 إضافي يعطيني الخطأ التالي:

Feb  4 17:12:11 web2 h2o[34490]: received fatal signal 11
Feb  4 17:12:11 web2 h2o[34490]: [34493] 0x4cf6a0 <???> at /usr/local/bin/h2o
Feb  4 17:12:11 web2 h2o[34490]: [34493] 0x8018c5946 <pthread_sigmask+0x536> at /lib/libthr.so.3
Feb  4 17:12:11 web2 h2o[34490]: [34493] 0x8018c4eb2 <pthread_getspecific+0xe12> at /lib/libthr.so.3

هل يوجد بالفعل حد منخفض على عدد مقاطع المسار المسموح بها ؟؟؟ لابد وانها حشره. من المحتمل أن يكون نفس السعر H2O.next .

نظرًا لأن كلاهما ، H2O.next و H20.reprocess يبدو أنهما معطلان ، كان علي استكشاف حل آخر. I نفذت معالج الوكيل العكسي في mruby بعدkazuho الصورة سبيل المثال .

يعمل هذا على خادم الاختبار الخاص بي. من المحتمل أن أنشره في الإنتاج قريبًا. ربما يساعد شخصًا آخر في مواجهة نفس المشكلات بالطرق المذكورة أعلاه:

proc {|env|
    # copy headers
    headers = {}
    env.each do |key, value|
      if /^HTTP_/.match(key)
        headers[$'] = value
      end
    end
    if env['CONTENT_TYPE']
        headers['CONTENT_TYPE'] = env['CONTENT_TYPE']
    end

    # issue the request
    input = env["rack.input"] ? env["rack.input"] : ""
    if env['QUERY_STRING'].to_s != ''
        uri = env['SCRIPT_NAME'] + env['PATH_INFO'] + '?' + env['QUERY_STRING']
    else
        uri = env['SCRIPT_NAME'] + env['PATH_INFO']
    end
    req = http_request(
      "http://<backend-ip>#{uri}",
      method:  env["REQUEST_METHOD"],
      headers: headers,
      body: input,
    )

    # Extract status, headers and body, so that I can look into the headers
    status, headers, body = req.join

    # actual work done here, if a certain header is present
    [status, headers, body]
}

لا يعمل بشكل جيد حتى الآن:
H2O أو mruby يحولان العنوان الأصلي CONTENT_TYPE إلى HTTP_CONTENT_TYPE ، مما يكسر خلفية WordPress ...

مثال:
"CONTENT_TYPE"=>"application/x-www-form-urlencoded; charset=UTF-8"
يصبح
"HTTP_CONTENT_TYPE"=>"application/x-www-form-urlencoded; charset=UTF-8"

هل هناك طريقة لفرض استخدام CONTENT_TYPE ؟

وكل هذا ، فقط لأنني أردت إضافة /path في h2o.conf الخاص بي ...

utrenkner آسف https://github.com/h2o/h2o/pull/2254 بإصلاح المشكلة. مع ذلك PR H2O.next و H2O.reprocess يعمل بشكل جيد على ما أعتقد

H2O أو mruby يحولان رأس CONTENT_TYPE الأصلي إلى HTTP_CONTENT_TYPE ، والذي يكسر خلفية WordPress ...

جربت نفس معالج mruby لكن لم أتمكن من إعادة إنتاجه. أعني ، لقد أنتجت الحد الأدنى من خادم المنبع ( echo -ne "HTTP/1.1 200 OK\r\n\r\n" | nc -l 9000 ) وشاهدت الرؤوس المرسلة من h2o. تضمنت CONTENT_TYPE ، وليس HTTP_CONTENT_TYPE .
راجع للشغل إذا كنت تتبع نهج http_request هذا ، فيجب عليك تحويل الشرطات السفلية في مفاتيح تجزئة الرأس إلى واصلات: أي ، يجب عليك تحويل HTTP_X_FOO إلى X-FOO ، وليس X_FOO . أعتقد أن هذا هو سبب هذه المشكلة: تطبيق الخادم الخاص بك لا يتعرف عليه كرأس content-type ، والذي يجب معالجته بشكل خاص في معظم الحالات.

@ i110 جزيل الشكر! سأجرب التصحيح الخاص بك ، غدا.

ونشكرك أيضًا على اختبار معالج mruby أعلاه. في الواقع ، لقد نسيت تمامًا تغيير الشرطة السفلية إلى واصلة. مع هذا التغيير ، فإنه يعمل على النحو المنشود و CONTENT_TYPE يبقى CONTENT_TYPE !

@ i110 شكرا جزيلا لك! # 2254 يحل مشاكلي مع كل من H2O.next و H2O.reprocess . لقد أضفت المزيد من مقاطع /path إلى h2o.conf ، فقط للتحقق من أنها تعمل بالفعل . ونعم ، هو كذلك!

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات