Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enable gzip encoding for capcitor http #6387

Closed
wants to merge 45 commits into from
Closed
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
659012f
init from https://github.com/capacitor-community/http/pull/222
Dante1349 Mar 12, 2023
f2f59cc
run prettier
Dante1349 Mar 12, 2023
2272fc3
fixed bug
Dante1349 Mar 12, 2023
b0be2ba
easier gzip
Dante1349 Mar 12, 2023
d12f6fc
fix
Dante1349 Mar 12, 2023
dcd4fb8
Revert "easier gzip"
Dante1349 Mar 14, 2023
52b3604
update pbxproj
Dante1349 Mar 14, 2023
aa58b9f
parse error
Dante1349 Mar 14, 2023
8cd4fe6
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 14, 2023
4656256
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 14, 2023
827dc35
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 16, 2023
a668f5f
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 18, 2023
d281a3e
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 28, 2023
739df49
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 29, 2023
b723810
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 30, 2023
ea4687d
Update package.json
Dante1349 Mar 30, 2023
f81a628
Merge branch 'main' into feature/http-gzip-support
Dante1349 Mar 31, 2023
f5dbb18
Merge branch 'main' into feature/http-gzip-support
Dante1349 Apr 4, 2023
450e1de
Merge branch 'main' into feature/http-gzip-support
Dante1349 Apr 11, 2023
32dd11b
Merge branch 'main' into feature/http-gzip-support
Dante1349 Apr 13, 2023
599cc06
Merge branch 'main' into feature/http-gzip-support
Dante1349 Apr 19, 2023
fb9e164
Merge branch 'main' into feature/http-gzip-support
Dante1349 Apr 21, 2023
d9d1b89
Merge branch 'main' into feature/http-gzip-support
Dante1349 Apr 21, 2023
a142f29
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 3, 2023
b851634
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 4, 2023
a0f39d9
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 8, 2023
55070ac
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 9, 2023
4ee77da
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 10, 2023
019fe0f
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 11, 2023
8109c63
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 13, 2023
aafa9bf
Merge branch 'main' into feature/http-gzip-support
Dante1349 May 23, 2023
6620192
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jun 18, 2023
1a625fc
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jun 29, 2023
8968fdb
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jul 6, 2023
ec9507a
Merge branch 'main' into feature/http-gzip-support
Dante1349 Nov 14, 2023
b5af74d
cleanup dependencies
Dante1349 Nov 14, 2023
2596273
Merge branch 'main' into feature/http-gzip-support
Dante1349 Nov 22, 2023
767f9a8
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jan 10, 2024
1e03ab6
fix pr
Dante1349 Jan 11, 2024
3fe706a
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jan 11, 2024
1ace063
Merge branch 'main' into feature/http-gzip-support
ItsChaceD Jan 17, 2024
635b6ef
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jan 19, 2024
df16fa0
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jan 23, 2024
f8100b3
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jan 25, 2024
7d3bc27
Merge branch 'main' into feature/http-gzip-support
Dante1349 Jan 30, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.zip.GZIPOutputStream;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
import org.json.JSONException;
Expand Down Expand Up @@ -191,6 +192,7 @@ public void setRequestBody(PluginCall call, JSValue body) throws JSONException,
*/
public void setRequestBody(PluginCall call, JSValue body, String bodyType) throws JSONException, IOException {
String contentType = connection.getRequestProperty("Content-Type");
Boolean gzipCompression = call.getBoolean("gzipCompression", false);
String dataString = "";

if (contentType == null || contentType.isEmpty()) return;
Expand All @@ -207,7 +209,7 @@ public void setRequestBody(PluginCall call, JSValue body, String bodyType) throw
} else if (body == null) {
dataString = call.getString("data");
}
this.writeRequestBody(dataString != null ? dataString : "");
this.writeRequestBody(dataString != null ? dataString : "", gzipCompression);
} else if (bodyType != null && bodyType.equals("file")) {
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Expand All @@ -221,12 +223,12 @@ public void setRequestBody(PluginCall call, JSValue body, String bodyType) throw
this.writeObjectRequestBody(obj);
} catch (Exception e) {
// Body is not a valid JSON, treat it as an already formatted string
this.writeRequestBody(body.toString());
this.writeRequestBody(body.toString(), false);
}
} else if (bodyType != null && bodyType.equals("formData")) {
this.writeFormDataRequestBody(contentType, body.toJSArray());
} else {
this.writeRequestBody(body.toString());
this.writeRequestBody(body.toString(), gzipCompression);
}
}

Expand All @@ -235,10 +237,17 @@ public void setRequestBody(PluginCall call, JSValue body, String bodyType) throw
*
* @param body The string value to write to the connection stream.
*/
private void writeRequestBody(String body) throws IOException {
try (DataOutputStream os = new DataOutputStream(connection.getOutputStream())) {
os.write(body.getBytes(StandardCharsets.UTF_8));
os.flush();
private void writeRequestBody(String body, boolean gzipCompression) throws IOException {
if (gzipCompression) {
try (GZIPOutputStream gos = new GZIPOutputStream(connection.getOutputStream())) {
gos.write(body.getBytes(StandardCharsets.UTF_8));
gos.flush();
}
} else {
try (DataOutputStream dos = new DataOutputStream(connection.getOutputStream())) {
dos.write(body.getBytes(StandardCharsets.UTF_8));
dos.flush();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -382,13 +382,19 @@ public static JSObject request(PluginCall call, String httpMethod, Bridge bridge
Integer readTimeout = call.getInt("readTimeout");
Boolean disableRedirects = call.getBoolean("disableRedirects");
Boolean shouldEncode = call.getBoolean("shouldEncodeUrlParams", true);
Boolean gzipCompression = call.getBoolean("gzipCompression", false);
ResponseType responseType = ResponseType.parse(call.getString("responseType"));
String dataType = call.getString("dataType");

String method = httpMethod != null ? httpMethod.toUpperCase(Locale.ROOT) : call.getString("method", "GET").toUpperCase(Locale.ROOT);

boolean isHttpMutate = method.equals("DELETE") || method.equals("PATCH") || method.equals("POST") || method.equals("PUT");

// Set gzip header if compression is enabled
if (gzipCompression) {
headers.put("Content-Encoding", "gzip");
}

URL url = new URL(urlString);
HttpURLConnectionBuilder connectionBuilder = new HttpURLConnectionBuilder()
.setUrl(url)
Expand Down
17 changes: 16 additions & 1 deletion core/src/core-plugins.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as Pako from 'pako';

import type { Plugin } from './definitions';
import { registerPlugin } from './global';
import { WebPlugin } from './web-plugin';
Expand Down Expand Up @@ -208,6 +210,11 @@ export interface HttpOptions {
* special handling in the native layer
*/
dataType?: 'file' | 'formData';
/**
* Use this option if you need a gzip compression of the data payload
* A compatible consumer interface must be ensured. The default is _false_.
*/
gzipCompression?: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this should be an on/off setting that is applied for the entire lifecycle of the plugin.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we will probably move this to a param in the http function call, this makes sense not to have it globally

}

export interface HttpParams {
Expand Down Expand Up @@ -318,7 +325,15 @@ export const buildRequestInit = (

// If body is already a string, then pass it through as-is.
if (typeof options.data === 'string') {
output.body = options.data;
if (options?.gzipCompression && options.headers) {
options.headers['Content-Encoding'] = 'gzip';
output.headers = options.headers;

const gzippedData: Uint8Array = Pako.gzip(options.data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of adding this dependency to core. Is there a reason you can't just gzip and gunzip on the client side from javascript on your side?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the thing is that we could do that, but why we switched to capacitor http is, that we need background functionality of the http services and therefore we started using capacitor-community/http which brought us here. The Pako compression could be done client side in the app code, but we moved it to the web part of the plugin to complete the gzip functionality for all platforms. I didn't find any good code example to do it without Pako, maybe this dependency can be kept?

output.body = gzippedData.buffer;
} else {
output.body = options.data;
}
}
// Build request initializers based off of content-type
else if (type.includes('application/x-www-form-urlencoded')) {
Expand Down
4 changes: 4 additions & 0 deletions ios/Capacitor/Capacitor.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
501CBAA71FC0A723009B0D4D /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 501CBAA61FC0A723009B0D4D /* WebKit.framework */; };
50503EE91FC08595003606DC /* Capacitor.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50503EDF1FC08594003606DC /* Capacitor.framework */; };
50503EEE1FC08595003606DC /* CapacitorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50503EED1FC08595003606DC /* CapacitorTests.swift */; };
5405D8B329C0949F008F945E /* Data+Gzip.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5405D8B129C0949F008F945E /* Data+Gzip.swift */; };
6214934725509C3F006C36F9 /* CAPInstanceConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6214934625509C3F006C36F9 /* CAPInstanceConfiguration.swift */; };
621ECCB72542045900D3D615 /* CAPBridgedJSTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 621ECCB42542045900D3D615 /* CAPBridgedJSTypes.m */; };
621ECCB82542045900D3D615 /* CAPBridgedJSTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 621ECCB62542045900D3D615 /* CAPBridgedJSTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
Expand Down Expand Up @@ -160,6 +161,7 @@
50503EDF1FC08594003606DC /* Capacitor.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Capacitor.framework; sourceTree = BUILT_PRODUCTS_DIR; };
50503EE81FC08595003606DC /* CapacitorTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CapacitorTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
50503EED1FC08595003606DC /* CapacitorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CapacitorTests.swift; sourceTree = "<group>"; };
5405D8B129C0949F008F945E /* Data+Gzip.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Data+Gzip.swift"; sourceTree = "<group>"; };
6214934625509C3F006C36F9 /* CAPInstanceConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CAPInstanceConfiguration.swift; sourceTree = "<group>"; };
621ECCB42542045900D3D615 /* CAPBridgedJSTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CAPBridgedJSTypes.m; sourceTree = "<group>"; };
621ECCB62542045900D3D615 /* CAPBridgedJSTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CAPBridgedJSTypes.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -408,6 +410,7 @@
62959AEA2524DA7700A3D7F1 /* Plugins */ = {
isa = PBXGroup;
children = (
5405D8B129C0949F008F945E /* Data+Gzip.swift */,
A327E6B428DB8B2900CA8B0A /* CapacitorHttp.swift */,
A327E6B528DB8B2900CA8B0A /* CapacitorUrlRequest.swift */,
A327E6B228DB8B2800CA8B0A /* HttpRequestHandler.swift */,
Expand Down Expand Up @@ -692,6 +695,7 @@
62959B362524DA7800A3D7F1 /* CAPBridgeViewController.swift in Sources */,
621ECCB72542045900D3D615 /* CAPBridgedJSTypes.m in Sources */,
62959B402524DA7800A3D7F1 /* TmpViewController.swift in Sources */,
5405D8B329C0949F008F945E /* Data+Gzip.swift in Sources */,
621ECCD6254205BD00D3D615 /* CAPBridgeProtocol.swift in Sources */,
62D43AF02581817500673C24 /* WKWebView+Capacitor.swift in Sources */,
62959B432524DA7800A3D7F1 /* Data+Capacitor.swift in Sources */,
Expand Down
17 changes: 15 additions & 2 deletions ios/Capacitor/Capacitor/Plugins/CapacitorUrlRequest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -185,11 +185,24 @@ open class CapacitorUrlRequest: NSObject, URLSessionTaskDelegate {
}
}

public func setRequestBody(_ body: JSValue, _ dataType: String? = nil) throws {
private func getRequestDataAsGzip(_ body: JSValue) throws -> Data? {
// string to Data
let dataBody = try getRequestDataAsString(body)

// gzip compression
let compressedData: Data = try dataBody.gzipped()
return compressedData
}

public func setRequestBody(_ body: JSValue, _ gzipCompression: Bool, _ dataType: String? = nil) throws {
let contentType = self.getRequestHeader("Content-Type") as? String

if contentType != nil {
request.httpBody = try getRequestData(body, contentType!, dataType)
if gzipCompression {
request.httpBody = try getRequestDataAsGzip(body)
} else {
request.httpBody = try getRequestData(body, contentType!, dataType)
}
}
}

Expand Down
Loading