H2o: Ошибка в H2O.next.call (env)

Созданный на 20 янв. 2020  ·  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, созданной из исходного кода по адресу

Все 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 кажутся неисправными, мне пришлось искать другое решение. Я осуществил обратный прокси - обработчик в mruby после @kazuho «s примера .

На моем тестовом сервере это работает. Я, скорее всего, скоро разверну его в производстве. Возможно, это поможет кому-то другому, столкнувшемуся с теми же проблемами с вышеупомянутыми методами:

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 рейтинги

Смежные вопросы

daniel-lucio picture daniel-lucio  ·  5Комментарии

basbebe picture basbebe  ·  3Комментарии

Ys88 picture Ys88  ·  5Комментарии

fetus-hina picture fetus-hina  ·  4Комментарии

ahupowerdns picture ahupowerdns  ·  8Комментарии