LINUX.ORG.RU

Кодирование json строки для передачи через ajax и php, хотелось бы единообразный подход

 , , , ,


0

2

Всех приветствую!

Что имеется ввиду?

Понял, занимаясь web-ом и десктопом на винде, что давно не могу разобраться - как кодировать json строку при передаче серверу через POST запрос.

Дело в том, что сейчас написал прогу под виндой, которая является сервером, и парсит входящие запросы (на С++).

На данный момент при передаче пост запроса клиент, указывает доп. параметр (в заголовке), что это запрос из js или php.

И далее на сервере я обрабатываю тело запроса (это кодированная json строка) соответственно по разному. И это все работает ОК.

Делаю я так потому, что для клиентов севера у меня есть так называемый АПИ с примерами вызовов.

И я хочу для пользователей (т.е. клиентов) сделать АПИ такой, чтобы они меньше заморачивались с кодированием/экранированием и прочей хренью в посылаемом пакете.

Но у меня пока получилось так:

  1. при передаче через ajax кодируем тело через encodeUriComponent.
  2. при передаче через php (curl) кодируем тело через json_encode.

Меня мучают сомнения, что это лучший вариант… Может есть более единообразный подход (по принципу чем клиенту проще тем лучше).


Может есть более единообразный подход

Ну да, кодировать и там и там в json например. Он более компактный. В чем проблема? Ну и принимать оба формата в общем-то тоже не проблема.

goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 3)
Ответ на: комментарий от goingUp

Ну только клиенту надо не забывать и не путать js или php параметр указывать (encode_str).

Просто у меня ощущение , что нет совместимости в этом вопросе у js и php.

Я пробовал найти точное соответствие какой-то одной функции в js и php, но без костылей не нашел. Вот это странно очень…

kkmspb
() автор топика
Ответ на: комментарий от kkmspb

Ну только клиенту надо не забывать и не путать js или php параметр указывать (encode_str)

А, я не сразу понял, так действительно не годится. Параметр не нужно, нужно на клиенте передавать заголовок Content-type а на сервере его проверять. Для json Content-Type: application/json; charset=utf-8 для urlencoded Content-Type: application/x-www-form-urlencoded; charset=utf-8 Вы проверьте, может уже заголовок передается как надо, нужно просто на сервере проверять.

нет совместимости в этом вопросе у js и php.

И js и php могут передавать данные обоими способами

goingUp ★★★★★
()
Ответ на: комментарий от goingUp

Чего-то сомнения взяли, а разве Content-Type: пользователь не может указать какой ему вздумается? Тогда какой смысл полагаться на это?

Просто я например говорю клиенту - надо EncodeUriComponent использовать перед передачей тела запроса (при js). Тут все понятно. А вот Content-Type пользователь вроде вообще любой может указать…

kkmspb
() автор топика
Ответ на: комментарий от kkmspb

разве Content-Type: пользователь не может указать какой ему вздумается?

может конечно сказать что прислал текст, но подсунуть джейсон но вам то до этого какое дело если вы джейсон ждёте. Контент тайп нужен что бы пользователь мог сказать какой он выбрал для общения если же их в ваше апи больше чем 1 вариант.

Noob_Linux ★★★★
()
Ответ на: комментарий от kkmspb

Чего-то сомнения взяли, а разве Content-Type: пользователь не может указать какой ему вздумается?

Нет, вот варианты которые я выше написал - это по стандарту. Указали json, сервер должен разбирать, как жейсон. Ну это же буквально и есть тип контента, жейсон или urlencoded)

goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 1)
Ответ на: комментарий от goingUp

Указали json, сервер должен разбирать, как жейсон

но ее (json) просто как строку utf8 нельзя передавать - правильно? Ее надо кодировать как-то по любому - правильно?

Иначе на сервак ничего не дойдет (в теле будет обычно пустота).

Вот у меня сейчас как: function sendAjaxJsonCommandsPacket( url , hhh , jsnStr , text) { aaaa(text)

jsnObj = encodeURIComponent( jsnStr );

var ajaxFn = function () 
{
	$.ajax(
	{
		url: url,
		method: 'POST',
		dataType: 'json',
		headers: hhh,
		data:jsnObj,
		async: false,
kkmspb
() автор топика
Последнее исправление: kkmspb (всего исправлений: 1)
Ответ на: комментарий от kkmspb

но ее (json) просто как строку utf8 нельзя передавать - правильно?

json кодируется же в строку (из массива данных делается строка, в формате жейсона), которая потом отправляется в теле запроса. При urlencoded происходит то же самое, просто кодируется по другому. Если в теле пустота, значит где-то что-то делается неправильно.

goingUp ★★★★★
()
Ответ на: комментарий от kkmspb

jsnObj = encodeURIComponent( jsnStr );

dataType: ‘json’

взаимоисключающие параграфы. Нужно так

jsnObj = JSON.stringify(jsnStr);

Если конечно jsnStr уже не содержит строку в формате жсон)

goingUp ★★★★★
()
Последнее исправление: goingUp (всего исправлений: 1)

Используй одинаковые стандартные механизмы для приема на сервере.

Пришел неверный заголовок контента (не json) - кидаешь исключение что неправильный контент

Пришел валидный заголовок, но не валидное тело - кидаешь исключение что неправильный запрос

400 ых ошибок полно, выбирай что показать клиенту - 400, 406, 415, 418(!), 422

Пусть клиент озабочивается составлением правильного запроса с правильными заголовками и правильным телом.

skyman ★★★★
()
Ответ на: комментарий от skyman

418(!)

Вот прямо сегодня видел вживую в дикой природе %)

Nervous ★★★★★
()

base64 В джаваскрипте это две функции: btoa() и atob()

qount_25
()
Ответ на: комментарий от kkmspb

но ее (json) просто как строку utf8 нельзя передавать - правильно?

нет

Ее надо кодировать как-то по любому - правильно?

нет

Иначе на сервак ничего не дойдет (в теле будет обычно пустота).

если ничего не отправить то и ничего не дойдет

судя по коду что ты продемонстрировал ты вообще не понимаешь что делаешь. Почитай документацию к $.ajax на примерах того как отправлять джейсоны - и внезапно будет понятно что делать буквально ничего не надо т.к. это поведение по умолчанию, а ты сделал что то странное.

Noob_Linux ★★★★
()

Похоже я ещё просто не учёл, что прилетает заголовок Expect: 100-continue (на сервер) и вроде по нему надо отвечать соответственно.

И ещё я тупо не учел, что тело может приходить частями.

Поэтому всем большое спасибо за отзывы, очень помогли.

Буду дальше разбираться.

kkmspb
() автор топика
Последнее исправление: kkmspb (всего исправлений: 1)
Ответ на: комментарий от targitaj

Ну base64 тоже вариант кодирования, ну компактный, и что? Чтобы его использовать надо вызывать методы его кодирования. В чем его преимущество?

kkmspb
() автор топика
Ответ на: комментарий от kkmspb

Нифига base64 не компактный и ничем он в данном случае не поможет, его просто используют в качестве костыля)

goingUp ★★★★★
()
Ответ на: комментарий от kaldeon

Попробую конечно попозже. У меня сервер на Qt под виндой написан, там UTF-8 везде используется, на клиенте у меня тоже js на UTF-8. Но при приеме на сервере сырого json (без кодирования как есть), а также если клиент через curl на php - на сервере получаю пустое тело…

kkmspb
() автор топика

Хотел добавить об одной странной проблеме в моей клиент сервере. Один товарищ прикрутил к своему сайту мой клиент. Сделал это на php. Посылает команды , получает ответы. Ответ это json строка примерно такого формата: [ { «aaa»:234, …… } ] Обратите внимание это список. Так вот не могу понять: у товарища при не большом передаваемом пакете в клиенте - ответ от сервера нормальный. А при пакете передаваемом серверу побольше, вдруг в ответе Нет первой квадратной скобки.Причем стабильно нет.

У меня на сайте при передаче пакетов аналогичных как у товарища все всегда ок, всегда все нормально.

Сервер я пишу сам на С++, это приложение под виндой и там логгирую все, что принимаю и передаю и там все нормально отдаю [{}] Но почему клиент у товарища может не получает первую скобку ума не приложу. Длину контента проверял многократно.

kkmspb
() автор топика

Движок яваскрипта строки хранит во внутренней кодировке… Поэтому страница может быть в CP1251, а данные получать в UTF-8 через AJAX и успешно отображать

rtxtxtrx ★★★
()
Ответ на: комментарий от kkmspb

Ты все делаешь через жопу. Отдавай JSON в UTF-8 с соответствующим заголовком (Content-Type: application/json; charset=UTF-8). Запросы же от пользователя обрабатывать так:

Смотрим Content-Type:

  • Если application/json ($mime = explode(';', $_SERVER["CONTENT_TYPE"]); if (strtolower($mime[0]) === "application/json")), то читаем сырой запрос, декодируем
  • Иначе берем данные из $_REQUEST либо $_GET/$_POST в новых версиях, где нет первого
rtxtxtrx ★★★
()
Последнее исправление: rtxtxtrx (всего исправлений: 1)
Ответ на: комментарий от kkmspb

У меня сервер на Qt под виндой написан

Не знаю что неуместнее: C++ на сервере или твоя винда на этом сайте

rtxtxtrx ★★★
()
Ответ на: комментарий от kkmspb

Еще вот логи с сервера показываю (тут стабильно все и на мой взгляд правльно)

——– прием ——– всего : 1142 байт

"POST / HTTP/1.1
Host: 109.188.142.134:44736
Accept: */*
Action: command_list
BIT_ENCODE_TYPE: PHP
BIT_ORDER_ID: 122
BIT_KKT_TOKEN: 435cb88c28fc49bd419d58d4b60680b5
Origin: https://kkmspb.ru
Content-Length: 872
Content-Type: application/x-www-form-urlencoded

[{"name":"2. \u0424\u0438\u0441\u043a\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u043c \u0447\u0435\u043a","type":"kktReceiptFiscalization","data":{"1261":[{"a_1262":"001","b_1263":"25.07.2025","c_1264":"001","d_1265":"jkersgdhfk8349544"}],"1059":[{"productName_1030":"\u041e\u0442\u043b\u0430\u0434\u043a\u0430 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u044b ","price_1079":1.23,"qty_1023":2.345,"amount_1043":2.88,"unit_2108":0,"paymentFormCode_1214":4,"productTypeCode_1212":1,"tax_1199":6}],"cashierName_1021":"\u041f\u0443\u043f\u043a\u0438\u043d \u0418\u0432\u0430\u043d \u0422\u0440\u043e\u0444\u0438\u043c\u043e\u0432\u0438\u0447","cashierInn_1203":"","payments":{"cash_1031":2.88,"ecash_1081":0,"prepayment_1215":0,"credit_1216":0,"barter_1217":0},"taxationType_1055":1,"receiptType_1054":1,"sendToEmail_1008":"kkmspb2008@yandex.ru","printDoc":true}}]" 

——– ответ ——– body 330 байт whole packet 417 байт

HTTP/1.1 200 OK
Content-Length: 330
Content-Type: application/json; charset=UTF-8

[
	{
		"info":{
			"checkNum_1042":5,
			"fiscalDocNum_1040":17,
			"fiscalSign_1077":"0357921044",
			"shiftNum_1038":2,
			"unixDateTime_1012":1747125780
		},
		"name":"2. Фискализируем чек",
		"result":true,
		"success":"чек пробит успешно",
		"type":"kktReceiptFiscalization"
	}
]

В ответе стабильно (на php 5.6 curl 7.29.0) в возврате у curl первый символ [ отсутствует.

перевод строки везде \r\n - правильно?

kkmspb
() автор топика
Последнее исправление: kkmspb (всего исправлений: 2)
Ответ на: комментарий от kkmspb

Попробую WinShark-ом посмотреть еще, что реально пролетает по tcp.

kkmspb
() автор топика
Последнее исправление: kkmspb (всего исправлений: 1)

Оказывается у товарища очень старый кастомный сервер, который трогать нельзя (предположим).

Так вот curl лажает с длиной пакета и stream_context_create лажает по непонятному закону.

Но оказывается у нас есть еще просто сокет вариант.

Тут уж никто не нагадит (я думаю). Попробую…

kkmspb
() автор топика
Ответ на: комментарий от kkmspb

В общем через сокеты все работает как надо!

Проблем не замечено пока.

Выводы: много глючных версий попадается curl, php , похоже это нормально.

Но теперь у нас есть инструмент, прога БИТ драйвер ккт, где в логах всегда можно посмотреть что принимает сервер от вас. И это дорогого стоит (как я осознал). Ибо никакие кодировки вас теперь не введут в заблуждение.

Правда прога под виндой, но это не суть. Главное результат достигнут.

kkmspb
() автор топика
Ответ на: комментарий от kkmspb

P S. Хотелось узнать у знатоков серводелов, есть ли где логи http запросов на сервер (именно сырые)? Это имеется ввиду на хостинге например.

Или как их включить?

kkmspb
() автор топика
Последнее исправление: kkmspb (всего исправлений: 1)
Ответ на: комментарий от kkmspb

Мне кажется таких логов не найти по причине опасности кражи данных. Но тогда, чтобы проверить передаваемые сырые данные надо велосипедист свой сервер.

kkmspb
() автор топика
Ответ на: комментарий от goingUp

Спасибо за ответы!

Теперь вроде все работает нормально (и на маленькой скорости, где были проблемы)

Реализовал поддержку от клиента 4 чипов контента:

Content-Type: application/json; charset=UTF-8
Content-Type: application/x-www-form-urlencoded
Content-Type: text/plain base64
Content-Type: text/plain hex

Остался вопрос как клиенту попросить у сервера отдавать ответ тоже в одном из этих четырех вариантах?

Или действовать по принципу: какой тип клиент сам используем в запросе, такой серверу и использовать в ответе?

kkmspb
() автор топика
Последнее исправление: kkmspb (всего исправлений: 1)
Ответ на: комментарий от goingUp

Но вообще, если и сервер и клиент твой, обычно просто делают жсон и все.

Сервер мой, а вот клиенты все кто угодно, все разнообразие php версий, curl, socket, stream_context_create. Потом js ajax.

В общем недавно намучался c php 5.6 curl 7.29.0 (у клиента кастомный линакс, нельзя менять). Так вот curl [] квадратные скобки в ответе клиент толи убирал, то ли игнорировал. Но в итоге я отдаю с сервера, а клиент получает без []. (это по json)

kkmspb
() автор топика
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.