Извините за длинный вопрос. Я работаю над модулем раку Net::Google::Sheets.
В настоящее время он успешно использует OAuth2::Client::Google, а также получает и помещает 2D-массив из/в Google Sheet.
Я хочу добавить метод $sheet.clear
в соответствии с Google Sheets API.
Вот соответствующий класс в /lib/Net/Google/Sheets.rakumod:
class Sheet is export {
has $.session;
has $.id;
has $.range;
method url {
"$sheet-base/{$!id}/values/{$!range}"
}
method clear {
my $request = HTTP::Request.new(
POST => ($.url ~ ':clear'),
Authorization => "Bearer {$.session.token}",
Content-length => 0,
);
$ua.request($request).decoded-content.&from-json;
}
}
И вот скрипт, который это вызывает:
#!/usr/bin/env raku
use Net::Google::Sheets;
my $session = Session.new;
my %sheets = $session.sheets;
my $id = %sheets<AWS_EC2_Sizes_test>;
$sheet2.clear; # <=== gives error
И вот вывод и ошибка, которую я получаю...
The requested URL <code>/v4/spreadsheets/{SheetId}/values/Sheet2%3Aclear</code> was not found on this server. <ins>That’s all we know.</ins>
Доступ Oauth работает нормально для чтения и записи, идентификатор листа правильный. Я также получил успешное действие .clear через поле «Попробуйте» в справочном документе Google.
Я подозреваю, что в gRPC есть какая-то тонкость, которую я не слежу (может быть, мне нужно закодировать символ двоеточия другим способом?).
Пожалуйста, можете ли вы помочь?
Благодаря ответу @raiph, см. ниже, проблема заключалась в том, что передача URI строки для всего URL-адреса означает, что вся она закодирована в URL-адресе, и (как указывает Раиф) Google хочет, чтобы двоеточие :
было как есть. Следующий код работает нормально:
method uri( :$cmd ) {
my $uri = URI.new: $sheet-url;
my $path = "$sheet-path/{$!id}/values/{$!range}";
$path ~= ":$cmd" if $cmd;
$uri.path: $path;
$uri;
}
method clear {
my $cmd = 'clear';
my $request = HTTP::Request.new(
POST => $.uri( :$cmd ),
Authorization => "Bearer {$.session.token}",
Content-length => 0,
);
$ua.request($request).decoded-content.&from-json;
}
Спасибо, что распутали меня!
...{spreadsheetId}/values/Feuille%202:clear
. Часть Feuille%202
представляет собой шестнадцатеричное пространство, но :clear
не кодирует :
. В своем модуле Net::Google::Sheets
вы вызываете HTTP::Request.new
. Предположительно, это шестнадцатеричная кодировка двоеточия, но «не должна».
Райф – спасибо за помощь (и извини за медленный ответ из-за $day-work) – пахнет как надо, я попробую и свяжусь с тобой..
@librasteve Это заняло у меня слишком много времени, но сейчас я доволен своим ответом! 😊
исправление выпущено на raku.land под номером v0.0.4.
Вы можете попробовать модуль URI::Encode
Раку:
«Кодируйте и декодируйте строки URI, как определено RFC 3986»
https://raku.land/zef:raku-community-modules/URI::Encode
Или (более конкретно) вы можете попробовать ord
и chr
:
в Раку РЕПЛ:
[0] > say "\c[COLON]".ord;
58
[0] > say "\c[COLON]".ord.chr;
:
Или просто chr
в одиночку:
[0] > say "58".chr;
:
https://unix.stackexchange.com/a/746206/227738
спасибо за ваш ответ... действительно, это проблемная область (см. мой комментарий к Раифу выше)... но он смог помочь с тем, как вручную создать объект URI, а затем применить путь отдельно, чтобы избежать кодировки uri
Следующее не тестировалось на месте с помощью HTTP::Request
и вызова конечной точки API листов Google, но я достаточно уверен, что это сработает, чтобы опубликовать его в качестве ответа:
my URI $uri .= new($.url) andthen .path(.path ~ ':clear');
my $request = HTTP::Request.new(POST => $uri, ...
Несколько замечаний о том, что я понял на пути к вышеуказанному решению, могут быть полезны для последующих читателей:
Мне потребовались часы/дни, чтобы понять это.
Пакеты сообщества для обработки такого рода вещей по умолчанию стараются делать все возможное, чтобы делать полезные вещи. В этом случае обработка двоеточия по умолчанию в части пути URI (например, бит foo/bar:baz
в http://example.com/foo.bar:baz#this?q=that
) заключается в его процентном кодировании. Но это означает, что ваш вызов HTTP::Request
не работает (поскольку API листов Google требует, чтобы двоеточие оставалось как есть).
Пакет, выполняющий эту кодировку, — URI::Path
. Он включает в себя метод Path.new
, который принимает аргументы, в том числе объект соответствия, содержащий запись пути из анализа грамматики Raku URI, и необязательный именованный аргумент scheme
. Учитывая значение схемы HTTP для последнего, строка пути проходит через фильтр unescape/escape - какой процент кодирует такие символы, как двоеточие. Хотя в целом это полезно, это также создает вашу проблему. К счастью, если Path.new
не передается именованный аргумент scheme
, то строка пути не проходит через этот фильтр. Итак, вызов Path.new
без аргумента scheme
стал тем, к чему я стремился.
Ваш код не использует URI::Path
напрямую. Но он включает аргумент POST
при вызове HTTP::Request.new
. Последний либо создает новый объект URI
из значения аргумента (если это строка), либо использует значение как есть (если оно уже является объектом URI
). Решение в этом ответе использует второй вариант, предварительно создавая объект URI
в два этапа. Сначала я создаю новый объект URI
из URL-адреса через URI.new
. На этом этапе любые двоеточия в части пути будут закодированы в процентах, но я проверяю, что :clear
не включен. Во-вторых, я: вызываю метод URI
с нулевым аргументом .path
(который возвращает объект Path
, представляющий часть пути объекта URI
, который при необходимости преобразуется в обычную строку); добавьте к нему ':clear'
; и я передаю эту последнюю строку в метод URI
с одним аргументом .path
, который обновляет атрибут $!path
объекта URI, вызывая Path.new
, опуская именованный аргумент scheme
. Это гарантирует, что двоеточие в пути не будет закодировано в процентах в конечном объекте URI
.
Я начал узнавать о том, как должны выглядеть соответствующие аспекты с точки зрения API, когда прочитал ключевую проблему, опубликованную в 2015 году: Создание URI из частей, которая начиналась так:
Было бы неплохо, если бы вы могли построить URI из частей (и правильно закодировать его без вашего участия). Если это уже возможно, то это следует задокументировать.
Прочитав этот выпуск, я открыл глаза.
2 года спустя Джонатан Стоу++ зафиксировал код, чтобы закрыть проблему. Последовали фиксации документов.
Вы уверены, что это не
URI::Encode
вещь?