yaws appmods Accept-Language Запись не верна - PullRequest
0 голосов
/ 04 октября 2019

Я работаю с рысканиями из контейнера докера годами, в основном взято с https://github.com/segeda/docker-yaws/blob/master/Dockerfile:

FROM erlang:20-alpine
...
&& git clone https://github.com/klacke/yaws.git /yaws-src \
...

Вещи, которые раньше просто работали нормально, но вдруг мой код не работает, и я не могу найтиошибка (ы). Я даже не смог найти версию git, которая работала раньше, поэтому я подозреваю, что это может быть не ошибка кода, но тогда - что это может быть?

Это не может быть мой код, не так ли? Потому что я свел его к примеру, приведенному в http://yaws.hyber.org/appmods.yaws, и выдал ту же ошибку:

%% this is my appmod called from yaws

-module(myurl).
-author('kklepper').
-include("../../include/yaws_api.hrl").
%-include("/usr/local/lib/yaws/include/yaws_api.hrl"). 
% relative or absolute -- either way same result
-export([out/1]).

-define(debug, true).
-ifdef(debug).
-define(trace(Str, X), io:format("Mod:~w line:~w ~p ~p~n", 
                                 [?MODULE,?LINE, Str, X])).
-else.
-define(trace(X, Y), true).
-endif.

box(Str) ->
    {'div',[{class,"box"}],
     {pre,[],Str}}.

out(A) ->
?trace('A', A),
    {ehtml,
     [{p,[],
       box(io_lib:format("A#arg.appmoddata = ~p~n"
                         "A#arg.appmod_prepath = ~p~n"
                         "A#arg.querydata = ~p~n",
                         [A#arg.appmoddata,
                          A#arg.appmod_prepath,
                          A#arg.querydata]))}]}.

Файл yaws_api.hrl был и остается:

/yaws # ls -la /usr/local/lib/yaws/include/yaws_api.hrl
-rw-r--r--    1 1000     50            5563 May 13  2018 /usr/local/lib/yaws/include/yaws_api.hrl

С trace вы можете видеть, что запись A неверна - нет A#arg.querydata и т. Д. - отсюда и ошибка. Почему?

Очевидно, например, querydata как таковое дано: lg=en.

Mod:myurl line:22 'A' {arg,#Port<0.2934>,
                          {{10,255,0,2},52801},
                          {headers,"keep-alive",
                              "text/html, application/xhtml+xml, application/xml;q=0.9, image/webp, image/apng, */*;q=0.8, application/signed-exchange;v=b3",
                              "voxx.b2d",undefined,undefined,undefined,
                              undefined,undefined,undefined,undefined,
                              "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36",
                              undefined,[],undefined,undefined,undefined,
                              undefined,undefined,undefined,undefined,
                              undefined,
                              [{http_header,11,'Accept-Language',undefined,
                                   "de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7"},
                               {http_header,10,'Accept-Encoding',undefined,
                                   "gzip, deflate"},
                               {http_header,0,"Upgrade-Insecure-Requests",
                                   undefined,"1"}]},
                          {http_request,'GET',
                              {abs_path,"/industries?lg=en"},
                              {1,1}},
                          {http_request,'GET',
                              {abs_path,"/industries?lg=en"},
                              {1,1}},
                          undefined,"/industries","lg=en","industries","/ci",
                          "/","/ci/industries",undefined,undefined,<0.163.0>,
                          [],[],[],"/industries",myurl}

=ERROR REPORT==== 4-Oct-2019::00:46:06 ===


ERROR erlang code threw an uncaught exception:
 File: appmod:0
Class: error
Exception: {badrecord,arg}
Req: {http_request,'GET',{abs_path,"/industries?lg=en"},{1,1}}
Stack: [{myurl,out,1,
               [{file,"/usr/local/lib/yaws/voxx/ebin/myurl.erl"},{line,29}]},
        {yaws_server,deliver_dyn_part,8,
                     [{file,"yaws_server.erl"},{line,2921}]},
        {yaws_server,aloop,4,[{file,"yaws_server.erl"},{line,1274}]},
        {yaws_server,acceptor0,2,[{file,"yaws_server.erl"},{line,1073}]},
        {proc_lib,init_p_do_apply,3,[{file,"proc_lib.erl"},{line,247}]}]

К настоящему времени у меня закончились идеи. Любой намек?

Данные, кажется, там. Меня интересуют, в частности, языковые данные, которые используются для получения принятого языка из A, например:

get_lang(A) -> 
    find_lang(find_http_header('Accept-Language', (A#arg.headers)#headers.other)).

find_http_header(Key,Headers) when is_list(Headers) ->
        case lists:keysearch(Key,3,Headers) of
            {value,{_,_,_,_,Value}} -> Value;
            false -> undefined
        end.

find_lang(AcceptLanguage) ->
    case AcceptLanguage of
        undefined ->
            "en";
        _ ->
            L = lists:nth(1,string:tokens(
                lists:nth(1,string:tokens(
                    lists:nth(1,string:tokens(AcceptLanguage, ";"))
                    ,","))
            ,"-")),
            L
    end.

Без правильной структуры данных это не может работать.

1 Ответ

1 голос
/ 08 октября 2019

Детали, включенные в ваш вопрос, показывают, что ваш appmod получает исключение badrecord при попытке получить доступ к записи #arg, которую Yaws передает ей. Есть несколько способов получить такое исключение:

  1. Передать экземпляр типа данных, отличный от ожидаемого типа записи, в функцию. В этом случае этого не происходит, поскольку Yaws вызывает функцию и правильно передает #arg экземпляр записи.
  2. Скомпилируйте вызывающую и вызываемую функцию с двумя различными определениями одной и той же записи. Мы можем смоделировать эту проблему в оболочке Эрланга следующим образом:
    • Сначала определите запись #arg, содержащую два поля
    • Определите функцию, которая принимает экземпляр этой записи в качестве аргумента и возвращаетзначение одного из полей
    • Переопределить запись в оболочке, чтобы иметь только одно поле
    • Передать экземпляр переопределенной записи в функцию, что вызовет исключение badrecord
        1> rd(arg, {f,g}).
        arg
        2> F = fun(A) -> A#arg.f end.
        #Fun<erl_eval.7.126501267>
        3> rd(arg, {f}).
        arg
        4> F(#arg{f=1}).
        ** exception error: {badrecord,arg}

Поскольку вы используете Yaws 2.0.7 и клонируете Yaws из github, вероятно, вы компилируете некоторую часть своего кода, возможно,appmod, против ветки master Yaws, а затем запустив ее против 2.0.7. Через некоторое время после того, как я пометил Yaws 2.0.7 на github, я принял изменение , которое добавило новое поле к определению записи #arg. Это означает, что любая #arg запись, которую Yaws 2.0.7 создает и передает вашему appmod, приведет к исключению badrecord, так как appmod ожидает запись, содержащую дополнительное поле.

Я могу вспомнитьВот несколько способов избежать этой проблемы:

  • Избавьтесь от своего клона Yaws github и соберите все, что вам нужно для установки Yaws 2.0.7.
  • В вашем клоне Yaws git checkout yaws-2.0.7 такчто все, что вы используете или используете с помощью клона, совпадает с тем, что есть в вашей установке Yaws 2.0.7.
  • Удалите Yaws 2.0.7, затем скомпилируйте и установите его с вашего клона Yaws. Возможно, сначала примените локальный тег, а затем соберите и установите его, чтобы ваши развертывания можно было легко воспроизвести, и чтобы вы могли получать обновления Yaws с github, не нарушая ничего локально.
...