Кресты / Говнокод #25695 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
std::string makeFormContent(const std::string & album,
                            const std::wstring & filename,
                            const std::string & boundary)
{
    static const std::string DELIM = "\r\n";
    std::ostringstream ss;
    std::ifstream file(filename, std::ios::binary);


    ss << boundary << DELIM;
    ss << "Content-Disposition: form-data; name=\"album\"" << DELIM << DELIM;
    ss << album << DELIM;

    ss << boundary << DELIM;
    ss << "Content-Disposition: form-data; name=\"image\"; filename=\"image\"" << DELIM << DELIM;
    ss << file.rdbuf() << DELIM;

    ss << boundary << DELIM << "--";

    return ss.str();
}

Заебали. Куча HTTP-либ под кресты, а банально сделать POST-запрос с multipart/form-data без кучи ебли нельзя. Приходится самому составлять, лол.

Именно поэтому я за «requests.post(url, data=data, files=files)».

Запостил: gost gost, (Updated )

Комментарии (120) RSS

    • <?php
      define('DELIM', "\r\n");
      
      makeFormContent($album, $filename, $boundary) {
          $file = file_get_contents($filename);
      
          $ss = $boundary . DELIM;
          $ss .= 'Content-Disposition: form-data; name="album"' . DELIM . DELIM;
          $ss .= $album . DELIM;
      
          $ss .= $boundary . DELIM;
          $ss .= 'Content-Disposition: form-data; name="image"; filename="image"' . DELIM . DELIM;
          $ss .= $file . DELIM;
      
          $ss .= $boundary . DELIM . "--";
      
          return $ss;
      }
      Ответить
      • Кстати, а что будет, если в файле случайно встретится строка, совпадающая со значением параметра boundary?
        Ответить
          • Значит, перед отправкой нужно сканировать весь файл на предмет того, не встретится ли в нём boundary, и, если встретилось, генерировать новое boundary и снова проверять? Или обычно проверяют задним числом, когда сервер уже получил обрезанный файл?
            Ответить
            • Да просто генерят какую-нибудь достаточно длинную хуйню и надеются, что её там нет. Один хер те же 128 бит совпадают чуть реже чем никогда.
              Ответить
              • И весь веб держится на такой тонкой ниточке???

                В то время, когда космические корабли бороздят Большой театр, когда выходят новые версии TLS с новыми протоколами шифрования и подписи, формы для отправки файлов собираются таким алхимическим способом???
                Ответить
                • Предлагаю строить из файла префиксное дерево и генерировать гарантированно уникальную boundary за logN.
                  Ответить
                  • я понимаю как с помощью префиксного дерева доказать что некоей последовательности в файле нет

                    а как ее сгенерировать?
                    Ответить
                    • Ну например хранить в каждой ноде глубину поддерева и идти от корня в самую мелкую сторону. Там ты найдёшь одну из кратчайших последовательностей, которых в файле нет.
                      Ответить
                  • Предлагаю приписать к файлу любую букву и считать полученную строку границей. Ибо её точно нет в файле.
                    Ответить
                    • Нельзя совсем любую. Нельзя приписывать байт, совпадающий с первым байтом файла, потому что тогда парсер решит, что мы передали пустой файл.

                      Например, содержимое файла ABC. Если мы возьмём в качестве границы ABCA, то получим:
                      ABCA
                      ABCABCA
                      Встретив второй раз ABCA, парсер решит, что это конец. А если добавим любой другой символ, то облома не будет:
                      ABCD
                      ABCABCD
                      Ответить
                    • Предлагаю оптимизацию: изменять первый символ файла и считать полученную строку границей. Сэкономим один байт.
                      Ответить
                • Шифрование и подписи тоже держатся на вероятности... Да и тот же git.

                  Более того, вся электроника построена на вероятности. Метастабильность при передаче данных между разными частотными доменами убрать никак нельзя, можно только загнать вероятность в угол и делать вид, что всё заебись... И что один случай за миллиарды лет никто не заметит.
                  Ответить
                  • Всё, что угодно в этом мире держится на вероятности.

                    Например банк развалится, если все разом заберут оттуда бабло.
                    Гугл ляжет, если все в мире в одну секунду решат что-то погуглить
                    Ответить
                      • Какова вероятность родить, например, слонопотама в следствие ошибок в днк?

                        Какова вероятность что генератор случайных чисел сгенерирует Войну и Мир?
                        Ответить
        • Давно хотел то же самое спросить.
          Ответить
          • Content-Length же можно указать для каждого файла? Тогда не надо будет искать boundary в его кишках.
            Ответить
            • Ещё можно закодировать файл в Base64 или во что-нибудь ещё (urlencode, например, но заэскейпить каждый символ). Тогда выбрать boundary будет легче.
              Ответить
                • Уже нет, государев айпифильтер угорел и утонул.
                  Ответить
              • Я как-то имплементировал эдакий «Base250»: кодирование произвольных байтиков набором из 250 возможных значений. Сделал царское кодирование: декодер читает байты, пока не встретится FF; следующий за FF байт — «специальный»: три его нижних бита определяют индекс в массиве «запрещённых» байт, а пять верхних — расстояние до следующего специального байта. В декодированном потоке специальный байт заменяется на запрещённый, индекс которого указан в нижних битах специального. В результате в идеальном случае (в исходном потоке запрещённые байты находятся на расстоянии не более ≈30) мы получаем оверхед ровно в 1 байт!
                Ответить
                • Дык если ты можешь передавать расстояние, то у тебя стрим достаточно стабилен и не ему не нужны все эти специальные символы. Так что и тупые чанки по 255 байт с длиной в первом байте сойдут. И ёбли на порядок меньше 🙂
                  Ответить
                • Или специальный байт тоже никогда не может принять запрещённое значение?
                  Ответить
                  • Да, так совпало, что он гарантированно получается разрешённым. Суть в том, что надо максимально компактно передать стрим бинарных данных через среду, в которой несколько байт к передаче запрещены (\x00, например).
                    Ответить
                      • Они, плюс дополнительная фильтрация от приложения.
                        Ответить
                    • Ну кстати прикольно получается. В стриме с рандомом один из 8 запрещённых символов будет выпадать с матожиданием как раз в 32 байта... А в непожатом будет дохуя нулей и всегда будет за что зацепиться.
                      Ответить
                    • Или всё-таки арифметический кодек с его ровным и гарантированным оверхедом в 0.43% будет лучше для пожатых данных?
                      Ответить
                          • Спасибо, очень элегантная штука. У меня ещё была проблема в очень сильной ограниченности размера — одно сообщение должно было умещаться в 150 символов, поэтому каждый байтик метаданных существенно увеличивал оверхед.
                            Ответить
                            • Там не надо метаданных, оверхед будет те самые 0.43%. Ну с округлением вверх до байта.
                              Ответить
                            • > шутка
                              > 150 символов
                              Ну вот смотри 150 символов по log2(250) бит это 1194 с лишним бита аля 149 байт (если округлить вниз). Куда плотнее то? И это на любых данных, тут не будет никаких ограничений на "нули не реже 30".
                              Ответить
                                • > битоёбом
                                  Напротив, арифметическое кодирование сбрасывает оковы битоёбства!

                                  Зачем, к примеру, тратить на число от 0 до 5 целых три бита, если достаточно 2.59?
                                  Ответить
                                • А если какой-нибудь флажок включается очень редко, то зачем мне тратить на false целый бит, если достаточно небольшой части бита (true при этом займёт несколько бит, но и хер с ним)?

                                  Долой неделимость битов!
                                  Ответить
                            • > если округлить вниз
                              А если не округлять, то 149 байт и целых 2 бита, в которые ты сможешь положить что-то полезное!
                              Ответить
                        • Если мы не знаем вероятности, это будет выглядеть тупо как перевод дробного числа от 0 до 1 из 256-ричной системы в 250-ричную.
                          Ответить
                        • Ну или можно делить твой файл на 250 в столбик и выписывать частные в выхлоп энкодера.
                          Ответить
                • > в нижних битах
                  > не более 30
                  Но ведь запрещённых символов 6, а не 8? Поэтому из 7.96 бит мы потратим 2.58 и у нас останется 5.38 бит чтобы записать расстояние от 0 до 40!

                  Для этого достаточно заюзать (dist * 6) + code вместо (dist << 3) | code. Ну и ремапнуть полученное число от 0 до 245 в разрешённые символы по табличке.
                  Ответить
                  • Отличное решение, так оверхед на рандомных данных вообще будет околонулевой!
                    Ответить
                    • Вообще говоря нет, ты теряешь 1 байт на каждом разрыве цепочки, а это не так уж редко, как бы не 1/2 на каждом спецсимволе... Надо считать, в общем. Но лень.
                      Ответить
  • Где здесь «ЗЩЫЕ-запрос», пщые?!
    Ответить
    • «ЗЩЫЕ-запросы» бывают с «аппликация/х-шшш-форм-урленкодед» и с «мультипарт/форм-дата». Первый вариант браузеры собирают для <форм метод="пост">, когда не нужно передавать файлы (когда передаются только текстовые поля и галочки), второй вариант браузеры собирают, когда нужно передавать файлы (когда присутствует поле <инпут тупе="филе">).
      Ответить
    • auto rest_client = restc_cpp::RestClient::Create();
      
      bool exception = false;
      auto promise = rest_client->ProcessWithPromiseT<std::string>([&](restc_cpp::Context & ctx) {
          std::string boundary = "41d148306c0b2d3d0dd779d462883b7c";
          auto content = makeFormContent(album, imagePath, "--" + boundary);
          try {
              auto response = restc_cpp::RequestBuilder(ctx)
                  .Post("https://api.imgur.com/3/image")
                  .AddHeader("Authorization", "Bearer " + std::string(authToken))
                  .Header("Content-Type", "multipart/form-data; boundary=" + boundary)
                  .Data(content)
                  .Execute();
              return response->GetBodyAsString();
          }
          catch (restc_cpp::RestcCppException e) {
              exception = true;
              return std::string(e.what());
          }
      });
      auto response = promise.get();

      Какая обработка исключений )))
      Ответить
      • > Какая обработка исключений )))

        Поэтому я за «PHP».
        Ответить
        • В go довольно удобный http-client c опциональной обработкой ошибок.

          resp, err := http.Post(...)
          if err != nil { 
          	...
          }
          Ответить
          • Питушок, засунь своё goвно туда, откуда взял. Его изобрели питухи анскильные, не осилившие в кресты (а кресты в свою очередь, не осилившие сишку).
            Так что, питух, пожалуйста, не надо.
            Покажи лучше что ты реально сам сделал.
            Ответить
          • На всякий случай напоминаю тебе, что отвечать безграмотному уёбку, который косит под superkiller1997, не нужно
            Ответить
      • >2k19
        >restc_cpp
        В кресты-бусты до сих пор не завезли удобных апи с быдлерами?
        Ответить
        • Есть какой-то «boost::http», но его дока в текстовом виде весит 250 килобайт и написана в лучших традициях крестового Стандарта. Короткие туториалы по нему не гуглятся (видимо, кроме создателей его так никто и не осилил), только красивые решения в таком духе:
          request_stream << "GET " << argv[2] << " HTTP/1.0\r\n";
          request_stream << "Host: " << argv[1] << "\r\n";
          request_stream << "Accept: */*\r\n";
          request_stream << "Connection: close\r\n\r\n";

          Багор, как есть багор!
          Ответить
            • Лол, всегда думал, что запятая в крестах не перегружается. Это ж такие поехавшие DSL'и можно наметапрограммировать!
              Ответить
              • class A{};
                
                const A& operator, (const A& a, const char* s)
                {
                    std::cout << s;
                    return a;
                }

                Забавные чудеса крестотипизации: cтоит проебать один const и оператор применяется только первый раз, но всё успешно конпелируется, ведь запятая работает со всеми типами, и я долго не мог понять в чем дело.

                Тогда почему он вообще применяется, если я написал "A a", а не "const A a"?
                Ответить
                • За перегрузку запятой надо отрезать хуй.
                  Ответить
                  • Я всегда хотел перегрузить запяточие.
                    Ответить
                    • Запяточие не оператор. Именно поэтому я за S" Forth" там нет никаких операторов, только слова, и переопределить можно всё.
                      Ответить
                • Ах да, динамический петушок забыл про шаблоны:
                  template <class T>
                  const A& operator, (const A& a, T x)
                  {
                      std::cout << " ой! ";
                      return a;
                  }
                  Как во время конпеляции выдать внятное сообщение об ошибке?
                  Ответить
                  • Вообще-то запятая должна возвращать правый аргумент. Какой анскилл )))
                    Ответить
                  • > Как во время конпеляции выдать внятное сообщение об ошибке?
                    static_assert(false, "Konpelyaciya upadet na etoi stroke");
                    static_assert(sizeof(int) == 4); // С C++17 можно пропустить сообщение об ошибке
                    Ответить
          • Высирать куски протокола в стрим. Мдяяяя.
            Зато низкоуровнево.
            Ответить
              • По-царски, это сделать свою "сверхбыструю", кривую, глючную реализацию сетевого стека, отрыгивая hexы прямо в драйвер какого-нибудь r8234.

                Очевидно что высокоопитумальный код http-клиента будет завязан на конкретную Царь-машину и совершенно непортируем куда-либо ещё.

                PS. Да и в целом, http — для анскилябр заедушных, не по-царски это. В нём много перепитушни анскильной.
                Ответить
                • > сделать свою сверхбыструю кривую
                  Сначала подумал, что речь о Curve25519.
                  Ответить
                  • И как же мне програмно высрать сигнал прямо в порт? Желательно пример кода на сишке.
                    Ответить
                      • "Реальный" - это как? Мне под прыщи. Но для винды или мака тоже рассмотрю.
                        Ответить
                • ведроидный сниффер так устроен
                  Ответить
      • > return std::string(e.what());


        типа ты такой хотел скачать страничку, а получил козу?
        Ответить
  • А если нам нужно передать файл на несколько гигабайтиков (образ DVD, например), то как лучше всего собирать подобную форму?
    Ответить
    • Для этого надо, чтобы сервер поддерживал POST-запросы большого размера (по-умолчанию большинство серверов поддерживают 2 GB). Адекватное решение — пересылать файл по частям через «JavaScript».
      Ответить
      • > POST-запросы большого размера
        Вообще странно, что в том же PHP сначала сервак полностью закачивает файл и только потом скрипт получает управление и решает, что делать с этим файлом (или вообще выбрасывает нахуй, лол).
        Ответить
          • Х.з., я ж не настоящий сварщик. Но в джавке (spring?) вроде можно было самому читать стрим от клиента. Если мне не привиделось.
            Ответить
            • Оно из стандартной либы на InputStreamax работало испокон веков.

              И клиент (java.net.URLConnection) и сервлеты (https://docs.oracle.com/javaee/6/api/javax/servlet/ServletRequest.html).

              Spring только даёт обёртки: restClient (не слишком удобный) и инъекцию этих requestов в аннотированные методы.
              Впрочем всё это и разные jersey умеют.
              Ответить
      • Это правда, что при некоторых видах авторизации произойдёт чудо и файл будет загружен дважды: один раз с 401, второй раз с auth header?
        Ответить
        • Если авторизацию делает скрипт, а не сервер - вполне возможно...
          Ответить
        • Кстати, а браузеры умеют отправлять Expect: 100-continue чтобы не заливать весь файл вслепую?
          Ответить
            • Судя по хромовскому багтрекеру - хуй там. Хром вообще отваливается по таймауту если инет медленный и файл не успел залиться 🙂
              Ответить
                • Вроде и у фф такая же херня. Только curl отправляет этот expect.
                  Ответить
                  • > ДЦП'шники ищут, как это отключить

                    - Холмс, но зачем?!
                    Ответить
                    • Мешает, видимо. Надо же сначала отправить 100 Continue и только потом получишь тело.
                      Ответить
                      • Понятно.

                        А я чего спросил, не повезло попасть на кровавый ъ-прайз, там коллега жаловался, что сервак работает именно вот так, как я выше написал. А они там гоняют достаточно толстые жисоны по несколько десятков мегабайт.
                        Ответить
                        • Ну можно попробовать HEAD'ом пингануть, а потом полноценный запрос...
                          Ответить
  • выкинь нахуй это говно, убери плюсики в конце
    Ответить

Добавить комментарий

Из-за тебя ушел bormand, guest!

    А не использовать ли нам bbcode?


    8