О плагине
Репозиторий плагина com.synconset.cordovaHTTP находится тут. Данный плагин примечателен возможностью SSL Pining’а для клиента android или ios приложений. Но плагин в том виде, в котором находится в репозитории github он подходит не для всех случаев работы с клиентом. Вкратце есть несколько претензий к его работе для android версии:
- любой post запрос, который отправляет json объект преобразуется в x-url-form-encoded
- обработка ошибок при отсутствии связи с сервером для android и ios
Как исправить post запрос для json объекта читаем далее
Post запрос для json объекта
Мы отправляем на сервер post запрос с заголовком application/json и в теле JSON объект, но сервер выплюнет ошибку, т.к. ему придет x-url-form-encoded. Это плагин жестко зашивает в свои post запросы такой заголовок(HttpRequest.java метод form) и преобразует JSON объекты в map. Мы же поправим CordovaHttpPost и не будет трогать HttpRequest.
Будем проверять заголовок на наличие application/json и отправлять напрямую, чтобы избежать вызова метода form, который модифицирует заголовок.
if (this.getHeaders().get(HttpRequest.HEADER_CONTENT_TYPE).contains(HttpRequest.CONTENT_TYPE_JSON)) { // отправляем напрямую, чтобы избежать вызова метода form, который модифицирует заголовок request.send(this.getParams().get(BODY_KEY).toString()); } else { request.form(this.getParams()); }
По ключу BODY_KEY мы достаем json объект из карты. Куда мы предварительно записываем в CordovaHttpPlugin.java
if (action.equals("post")) { String urlString = args.getString(0); JSONObject params = args.getJSONObject(1); JSONObject headers = args.getJSONObject(2); HashMap<String, String> headersMap = this.addToMap(this.globalHeaders, headers); HashMap<?, ?> paramsMap = this.putJSONObjectToParamsMap(headersMap, params); CordovaHttpPost post = new CordovaHttpPost(urlString, paramsMap, headersMap, callbackContext); cordova.getThreadPool().execute(post); }
С помощью вспомогательного метода.
/** * Заносим в карту JSON объект если заголовок запроса указывает на application/json * @param headersMap карта с заголовками * @param jsonObject объект для тела запроса * @return карту тела запроса * @throws JSONException */ private HashMap<String, Object> putJSONObjectToParamsMap(HashMap<String, String> headersMap, JSONObject jsonObject) throws JSONException { if (headersMap.get(HttpRequest.HEADER_CONTENT_TYPE).contains(HttpRequest.CONTENT_TYPE_JSON)) { HashMap<String, Object> map = new HashMap<String, Object>(); map.put(CordovaHttpPost.BODY_KEY, jsonObject); return map; } else { return this.getMapFromJSONObject(jsonObject); } }
Удивительно не предусмотреть post запрос, который отправляет json объекты, но мы исправили данную оплошность разработчиков плагина.