Патчим плагин cordovaHTTP

О плагине

Репозиторий плагина 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 объекты, но мы исправили данную оплошность разработчиков плагина.

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