From 6b6fbaabc9447448c7f40e5e3f321c6930b32d1c Mon Sep 17 00:00:00 2001 From: Dick Smith Date: Tue, 17 Apr 2018 10:47:51 -0400 Subject: [PATCH 1/5] Fix/improve error handling Included latest typings from `net.gotev.uploadservice` which shows a change in the signature of `onError` from: `onError(context: any, uploadInfo: UploadInfo, error) {}` to: `onError(context: Context, uploadInfo: UploadInfo, serverResponse: ServerResponse, error: java.lang.Exception) {}` Also, the `error` was also not being passed to the new `zonedOnError` function. Also added the responseCode in the `ErrorEventData` in a cross-platform matter to allow apps to respond accordingly. --- src/background-http.android.ts | 63 +- src/background-http.ios.ts | 11 +- src/index.d.ts | 14 +- src/typings/java!uploadservice-3.4.2.ts | 1078 +++++++++++++++++++++++ 4 files changed, 1126 insertions(+), 40 deletions(-) create mode 100644 src/typings/java!uploadservice-3.4.2.ts diff --git a/src/background-http.android.ts b/src/background-http.android.ts index 2463962..7949656 100644 --- a/src/background-http.android.ts +++ b/src/background-http.android.ts @@ -1,24 +1,18 @@ -import application = require("application"); +import * as application from "application"; import { Observable } from "data/observable"; import { ad } from "utils/utils"; import * as fileSystemModule from "file-system"; import * as common from "./index"; -declare const net: any; -interface UploadInfo { - getUploadId(): string; - getTotalBytes(): number; - getUploadedBytes(): number; -} - -interface ServerResponse { - getBodyAsString(): string; -} +type Context = android.content.Context; +type ServerResponse = net.gotev.uploadservice.ServerResponse; +type UploadInfo = net.gotev.uploadservice.UploadInfo; +type UploadServiceBroadcastReceiver = net.gotev.uploadservice.UploadServiceBroadcastReceiver; /* A snapshot-friendly, lazy-loaded class for ProgressReceiver BEGIN */ let ProgressReceiver: any; -function onProgressReceiverProgress(context: any, uploadInfo: UploadInfo) { +function onProgressReceiverProgress(context: Context, uploadInfo: UploadInfo) { const uploadId = uploadInfo.getUploadId(); const task = Task.fromId(uploadId); const totalBytes = uploadInfo.getTotalBytes(); @@ -29,21 +23,26 @@ function onProgressReceiverProgress(context: any, uploadInfo: UploadInfo) { task.notify({ eventName: "progress", object: task, currentBytes: currentBytes, totalBytes: totalBytes }); } -function onProgressReceiverCancelled(context: any, uploadInfo: UploadInfo) { +function onProgressReceiverCancelled(context: Context, uploadInfo: UploadInfo) { const uploadId = uploadInfo.getUploadId(); const task = Task.fromId(uploadId); task.setStatus("cancelled"); task.notify({ eventName: "cancelled", object: task }); } -function onProgressReceiverError(context: any, uploadInfo: UploadInfo, error) { +function onProgressReceiverError(context: Context, uploadInfo: UploadInfo, response: ServerResponse, error: java.lang.Exception) { const uploadId = uploadInfo.getUploadId(); const task = Task.fromId(uploadId); task.setStatus("error"); - task.notify({ eventName: "error", object: task, error: error }); + task.notify({ + eventName: "error", + object: task, + error, + responseCode: response && typeof response.getHttpCode === 'function' ? response.getHttpCode() : -1 + }); } -function onProgressReceiverCompleted(context: any, uploadInfo: UploadInfo, serverResponse: ServerResponse) { +function onProgressReceiverCompleted(context: Context, uploadInfo: UploadInfo, serverResponse: ServerResponse) { const uploadId = uploadInfo.getUploadId(); const task = Task.fromId(uploadId); @@ -70,23 +69,25 @@ function initializeProgressReceiver() { const zonedOnError = global.zonedCallback(onProgressReceiverError); const zonedOnCompleted = global.zonedCallback(onProgressReceiverCompleted); - const ProgressReceiverImpl = net.gotev.uploadservice.UploadServiceBroadcastReceiver.extend({ - onProgress(context: any, uploadInfo: UploadInfo) { - zonedOnProgress(context, uploadInfo); - }, + const temp: Partial = { + onProgress(context: Context, uploadInfo: UploadInfo) { + zonedOnProgress(context, uploadInfo); + }, - onCancelled(context: any, uploadInfo: UploadInfo) { - zonedOnCancelled(context, uploadInfo); - }, + onCancelled(context: Context, uploadInfo: UploadInfo) { + zonedOnCancelled(context, uploadInfo); + }, - onError(context: any, uploadInfo: UploadInfo, error) { - zonedOnError(context, uploadInfo); - }, + onError(context: Context, uploadInfo: UploadInfo, response: ServerResponse, error: java.lang.Exception) { + zonedOnError(context, uploadInfo, response, error); + }, - onCompleted(context: any, uploadInfo: UploadInfo, serverResponse: ServerResponse) { - zonedOnCompleted(context, uploadInfo, serverResponse); - } - }); + onCompleted(context: Context, uploadInfo: UploadInfo, serverResponse: ServerResponse) { + zonedOnCompleted(context, uploadInfo, serverResponse); + } + }; + + const ProgressReceiverImpl = (net.gotev.uploadservice.UploadServiceBroadcastReceiver).extend(temp); ProgressReceiver = ProgressReceiverImpl as any; } @@ -309,4 +310,4 @@ class Task extends ObservableBase { cancel(): void { (net).gotev.uploadservice.UploadService.stopUpload(this._id); } -} \ No newline at end of file +} diff --git a/src/background-http.ios.ts b/src/background-http.ios.ts index 9b2f8d5..cec432d 100644 --- a/src/background-http.ios.ts +++ b/src/background-http.ios.ts @@ -28,7 +28,7 @@ class BackgroundUploadDelegate extends NSObject implements NSURLSessionDelegate, } // NSURLSessionTaskDelegate - URLSessionTaskDidCompleteWithError(session, nsTask, error) { + URLSessionTaskDidCompleteWithError(session: NSURLSession, nsTask: NSURLSessionTask, error: NSError) { dispatch_async(main_queue, () => { const task = Task.getTask(session, nsTask); if (task._fileToCleanup) { @@ -37,7 +37,12 @@ class BackgroundUploadDelegate extends NSObject implements NSURLSessionDelegate, } if (error) { task.notifyPropertyChange("status", task.status); - task.notify({ eventName: "error", object: task, error: error }); + task.notify({ + eventName: "error", + object: task, + error, + responseCode: nsTask && nsTask.response ? (nsTask.response).statusCode : -1 + }); } else { task.notifyPropertyChange("upload", task.upload); task.notifyPropertyChange("totalUpload", task.totalUpload); @@ -359,4 +364,4 @@ class MultiMultiPartForm { }; -} \ No newline at end of file +} diff --git a/src/index.d.ts b/src/index.d.ts index eab7d28..1e94959 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -13,7 +13,9 @@ export interface ErrorEventData extends observable.EventData { /** * Provides the underlying error. The value is platform specific. */ - error: any; + error: any /*NSError | java.lang.Exception*/; + /** HTTP response code if response object is present, otherwise -1 */ + responseCode: number; } /** @@ -32,11 +34,11 @@ export interface ProgressEventData extends observable.EventData { } /** - * Provides the server responce. + * Provides the server response. */ export interface ResultEventData extends observable.EventData { /** - * The string responce of the server. + * The string response of the server. */ data: string; } @@ -90,15 +92,15 @@ export interface Task { /** * Subscribe for progress notifications. * @param event - * @param handler A handler that will receive a progress event with the current and expected total bytes + * @param handler A handler that will receive a progress event with the current and expected total bytes * @event */ on(event: "progress", handler: (e: ProgressEventData) => void): void; /** - * Upon successful upload provides the server responce. + * Upon successful upload provides the server response. * @param event - * @param handler A handler that will receive the responce event. + * @param handler A handler that will receive the response event. * @event */ on(event: "responded", handler: (e: ResultEventData) => void): void; diff --git a/src/typings/java!uploadservice-3.4.2.ts b/src/typings/java!uploadservice-3.4.2.ts new file mode 100644 index 0000000..e3d9107 --- /dev/null +++ b/src/typings/java!uploadservice-3.4.2.ts @@ -0,0 +1,1078 @@ +/* tslint:disable */ +import androidcontentContext = android.content.Context; +import javalangClass = java.lang.Class; +import javautilList = java.util.List; +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class BinaryUploadRequest extends net.gotev.uploadservice.HttpUploadRequest { + public addParameter(param0: string, param1: string): net.gotev.uploadservice.BinaryUploadRequest; + public constructor(param0: androidcontentContext, param1: string); + public addArrayParameter(param0: string, param1: javautilList): net.gotev.uploadservice.HttpUploadRequest; + public constructor(param0: androidcontentContext, param1: string, param2: string); + public startUpload(): string; + public addArrayParameter(param0: string, param1: native.Array): net.gotev.uploadservice.BinaryUploadRequest; + public addParameter(param0: string, param1: string): net.gotev.uploadservice.HttpUploadRequest; + public addArrayParameter(param0: string, param1: javautilList): net.gotev.uploadservice.BinaryUploadRequest; + public getTaskClass(): javalangClass; + public setFileToUpload(param0: string): net.gotev.uploadservice.BinaryUploadRequest; + public addArrayParameter(param0: string, param1: native.Array): net.gotev.uploadservice.HttpUploadRequest; + } + } + } +} + +/// +declare module net { + export module gotev { + export module uploadservice { + export class BinaryUploadTask extends net.gotev.uploadservice.HttpUploadTask { + public onBodyReady(param0: net.gotev.uploadservice.http.BodyWriter): void; + public onBytesWritten(param0: number): void; + public onSuccessfulUpload(): void; + public getBodyLength(): number; + public shouldContinueWriting(): boolean; + public constructor(); + } + } + } +} + +import androidcontentIntent = android.content.Intent; +import androidosParcel = android.os.Parcel; +import javalangException = java.lang.Exception; +import androidosParcelableCreator = android.os.Parcelable.Creator; +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class BroadcastData { + public static CREATOR: androidosParcelableCreator; + public getException(): javalangException; + public writeToParcel(param0: androidosParcel, param1: number): void; + public setException(param0: javalangException): net.gotev.uploadservice.BroadcastData; + public getUploadInfo(): net.gotev.uploadservice.UploadInfo; + public getIntent(): androidcontentIntent; + public setStatus(param0: net.gotev.uploadservice.BroadcastData.Status): net.gotev.uploadservice.BroadcastData; + public describeContents(): number; + public setUploadInfo(param0: net.gotev.uploadservice.UploadInfo): net.gotev.uploadservice.BroadcastData; + public getServerResponse(): net.gotev.uploadservice.ServerResponse; + public getStatus(): net.gotev.uploadservice.BroadcastData.Status; + public setServerResponse(param0: net.gotev.uploadservice.ServerResponse): net.gotev.uploadservice.BroadcastData; + public constructor(); + } + export module BroadcastData { + export class Status { + public static IN_PROGRESS: net.gotev.uploadservice.BroadcastData.Status; + public static ERROR: net.gotev.uploadservice.BroadcastData.Status; + public static COMPLETED: net.gotev.uploadservice.BroadcastData.Status; + public static CANCELLED: net.gotev.uploadservice.BroadcastData.Status; + public static values(): native.Array; + public static valueOf(param0: string): net.gotev.uploadservice.BroadcastData.Status; + } + } + } + } +} + +declare module net { + export module gotev { + export module uploadservice { + export class BuildConfig { + public static DEBUG: boolean; + public static APPLICATION_ID: string; + public static BUILD_TYPE: string; + public static FLAVOR: string; + public static VERSION_CODE: number; + public static VERSION_NAME: string; + public constructor(); + } + } + } +} + +/// +declare module net { + export module gotev { + export module uploadservice { + export class ContentType { + public static APPLICATION_ENVOY: string; + public static APPLICATION_FRACTALS: string; + public static APPLICATION_FUTURESPLASH: string; + public static APPLICATION_HTA: string; + public static APPLICATION_INTERNET_PROPERTY_STREAM: string; + public static APPLICATION_MAC_BINHEX40: string; + public static APPLICATION_MS_WORD: string; + public static APPLICATION_OCTET_STREAM: string; + public static APPLICATION_ODA: string; + public static APPLICATION_OLESCRIPT: string; + public static APPLICATION_PDF: string; + public static APPLICATION_PICS_RULES: string; + public static APPLICATION_PKCS10: string; + public static APPLICATION_PKIX_CRL: string; + public static APPLICATION_POSTSCRIPT: string; + public static APPLICATION_RTF: string; + public static APPLICATION_SETPAY: string; + public static APPLICATION_SETREG: string; + public static APPLICATION_MS_EXCEL: string; + public static APPLICATION_MS_OUTLOOK: string; + public static APPLICATION_MS_PKICERTSTORE: string; + public static APPLICATION_MS_PKISECCAT: string; + public static APPLICATION_MS_PKISTL: string; + public static APPLICATION_MS_POWERPOINT: string; + public static APPLICATION_MS_PROJECT: string; + public static APPLICATION_MS_WORKS: string; + public static APPLICATION_WINHLP: string; + public static APPLICATION_BCPIO: string; + public static APPLICATION_CDF: string; + public static APPLICATION_Z: string; + public static APPLICATION_TGZ: string; + public static APPLICATION_CPIO: string; + public static APPLICATION_CSH: string; + public static APPLICATION_DIRECTOR: string; + public static APPLICATION_DVI: string; + public static APPLICATION_GTAR: string; + public static APPLICATION_GZIP: string; + public static APPLICATION_HDF: string; + public static APPLICATION_INTERNET_SIGNUP: string; + public static APPLICATION_IPHONE: string; + public static APPLICATION_JAVASCRIPT: string; + public static APPLICATION_LATEX: string; + public static APPLICATION_MS_ACCESS: string; + public static APPLICATION_MS_CARD_FILE: string; + public static APPLICATION_MS_CLIP: string; + public static APPLICATION_MS_DOWNLOAD: string; + public static APPLICATION_MS_MEDIAVIEW: string; + public static APPLICATION_MS_METAFILE: string; + public static APPLICATION_MS_MONEY: string; + public static APPLICATION_MS_PUBLISHER: string; + public static APPLICATION_MS_SCHEDULE: string; + public static APPLICATION_MS_TERMINAL: string; + public static APPLICATION_MS_WRITE: string; + public static APPLICATION_NET_CDF: string; + public static APPLICATION_PERFMON: string; + public static APPLICATION_PKCS_12: string; + public static APPLICATION_PKCS_7_CERTIFICATES: string; + public static APPLICATION_PKCS_7_CERTREQRESP: string; + public static APPLICATION_PKCS_7_MIME: string; + public static APPLICATION_PKCS_7_SIGNATURE: string; + public static APPLICATION_SH: string; + public static APPLICATION_SHAR: string; + public static APPLICATION_SHOCKWAVE_FLASH: string; + public static APPLICATION_STUFFIT: string; + public static APPLICATION_SV4CPIO: string; + public static APPLICATION_SV4CRC: string; + public static APPLICATION_TAR: string; + public static APPLICATION_TCL: string; + public static APPLICATION_TEX: string; + public static APPLICATION_TEXINFO: string; + public static APPLICATION_TROFF: string; + public static APPLICATION_TROFF_MAN: string; + public static APPLICATION_TROFF_ME: string; + public static APPLICATION_TROFF_MS: string; + public static APPLICATION_USTAR: string; + public static APPLICATION_WAIS_SOURCE: string; + public static APPLICATION_X509_CA_CERT: string; + public static APPLICATION_PKO: string; + public static APPLICATION_ZIP: string; + public static APPLICATION_XML: string; + public static AUDIO_BASIC: string; + public static AUDIO_MID: string; + public static AUDIO_MPEG: string; + public static AUDIO_AIFF: string; + public static AUDIO_M3U: string; + public static AUDIO_REAL_AUDIO: string; + public static AUDIO_WAV: string; + public static IMAGE_BMP: string; + public static IMAGE_COD: string; + public static IMAGE_GIF: string; + public static IMAGE_IEF: string; + public static IMAGE_JPEG: string; + public static IMAGE_PIPEG: string; + public static IMAGE_SVG: string; + public static IMAGE_TIFF: string; + public static IMAGE_CMU_RASTER: string; + public static IMAGE_CMX: string; + public static IMAGE_ICO: string; + public static IMAGE_PORTABLE_ANYMAP: string; + public static IMAGE_PORTABLE_BITMAP: string; + public static IMAGE_PORTABLE_GRAYMAP: string; + public static IMAGE_PORTABLE_PIXMAP: string; + public static IMAGE_XRGB: string; + public static IMAGE_XBITMAP: string; + public static IMAGE_XPIXMAP: string; + public static IMAGE_XWINDOWDUMP: string; + public static TEXT_CSS: string; + public static TEXT_CSV: string; + public static TEXT_H323: string; + public static TEXT_HTML: string; + public static TEXT_IULS: string; + public static TEXT_PLAIN: string; + public static TEXT_RICHTEXT: string; + public static TEXT_SCRIPTLET: string; + public static TEXT_TAB_SEPARATED_VALUES: string; + public static TEXT_VIEWVIEW: string; + public static TEXT_COMPONENT: string; + public static TEXT_SETEXT: string; + public static TEXT_VCARD: string; + public static TEXT_XML: string; + public static VIDEO_MPEG: string; + public static VIDEO_MPEG4: string; + public static VIDEO_QUICKTIME: string; + public static VIDEO_LA_ASF: string; + public static VIDEO_MS_ASF: string; + public static VIDEO_AVI: string; + public static VIDEO_MOVIE: string; + public static autoDetect(param0: string): string; + } + } + } +} + +import javalangThrowable = java.lang.Throwable; +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class DefaultLoggerDelegate { + public info(param0: string, param1: string): void; + public debug(param0: string, param1: string): void; + public error(param0: string, param1: string): void; + public constructor(); + public error(param0: string, param1: string, param2: javalangThrowable): void; + } + } + } +} + +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export abstract class HttpUploadRequest extends net.gotev.uploadservice.UploadRequest { + public httpParams: net.gotev.uploadservice.HttpUploadTaskParameters; + public addHeader(param0: string, param1: string): net.gotev.uploadservice.HttpUploadRequest; + public addArrayParameter(param0: string, param1: javautilList): net.gotev.uploadservice.HttpUploadRequest; + public setMethod(param0: string): net.gotev.uploadservice.HttpUploadRequest; + public constructor(param0: androidcontentContext, param1: string, param2: string); + public setUsesFixedLengthStreamingMode(param0: boolean): net.gotev.uploadservice.HttpUploadRequest; + public addParameter(param0: string, param1: string): net.gotev.uploadservice.HttpUploadRequest; + public addArrayParameter(param0: string, param1: native.Array): net.gotev.uploadservice.HttpUploadRequest; + public initializeIntent(param0: androidcontentIntent): void; + public setCustomUserAgent(param0: string): net.gotev.uploadservice.HttpUploadRequest; + public setBasicAuth(param0: string, param1: string): net.gotev.uploadservice.HttpUploadRequest; + } + } + } +} + +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export abstract class HttpUploadTask extends net.gotev.uploadservice.UploadTask implements net.gotev.uploadservice.http.HttpConnection.RequestBodyDelegate, net.gotev.uploadservice.http.BodyWriter.OnStreamWriteListener { + public httpParams: net.gotev.uploadservice.HttpUploadTaskParameters; + public onBodyReady(param0: net.gotev.uploadservice.http.BodyWriter): void; + public onBytesWritten(param0: number): void; + public init(param0: net.gotev.uploadservice.UploadService, param1: androidcontentIntent): void; + public upload(): void; + public getBodyLength(): number; + public shouldContinueWriting(): boolean; + public constructor(); + } + } + } +} + +import javautilArrayList = java.util.ArrayList; +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class HttpUploadTaskParameters { + public static PARAM_HTTP_TASK_PARAMETERS: string; + public customUserAgent: string; + public method: string; + public usesFixedLengthStreamingMode: boolean; + public static CREATOR: androidosParcelableCreator; + public getRequestParameters(): javautilArrayList; + public writeToParcel(param0: androidosParcel, param1: number): void; + public isCustomUserAgentDefined(): boolean; + public getRequestHeaders(): javautilArrayList; + public describeContents(): number; + public addHeader(param0: string, param1: string): net.gotev.uploadservice.HttpUploadTaskParameters; + public addParameter(param0: string, param1: string): net.gotev.uploadservice.HttpUploadTaskParameters; + public constructor(); + } + } + } +} + +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class Logger { + public static error(param0: string, param1: string, param2: javalangThrowable): void; + public static resetLoggerDelegate(): void; + public static setLoggerDelegate(param0: net.gotev.uploadservice.Logger.LoggerDelegate): void; + public static debug(param0: string, param1: string): void; + public static info(param0: string, param1: string): void; + public static setLogLevel(param0: net.gotev.uploadservice.Logger.LogLevel): void; + public static error(param0: string, param1: string): void; + } + export module Logger { + export class LogLevel { + public static DEBUG: net.gotev.uploadservice.Logger.LogLevel; + public static INFO: net.gotev.uploadservice.Logger.LogLevel; + public static ERROR: net.gotev.uploadservice.Logger.LogLevel; + public static OFF: net.gotev.uploadservice.Logger.LogLevel; + public static values(): native.Array; + public static valueOf(param0: string): net.gotev.uploadservice.Logger.LogLevel; + } + export class LoggerDelegate { + /** + * Constructs a new instance of the net.gotev.uploadservice.Logger$LoggerDelegate interface with the provided implementation. + */ + public constructor(implementation: { + error(param0: string, param1: string): void; + error(param0: string, param1: string, param2: javalangThrowable): void; + debug(param0: string, param1: string): void; + info(param0: string, param1: string): void; + }); + public error(param0: string, param1: string, param2: javalangThrowable): void; + public info(param0: string, param1: string): void; + public error(param0: string, param1: string): void; + public debug(param0: string, param1: string): void; + } + export class SingletonHolder { + } + } + } + } +} + +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class MultipartUploadRequest extends net.gotev.uploadservice.HttpUploadRequest { + public addFileToUpload(param0: string, param1: string): net.gotev.uploadservice.MultipartUploadRequest; + public constructor(param0: androidcontentContext, param1: string); + public addFileToUpload(param0: string, param1: string, param2: string, param3: string): net.gotev.uploadservice.MultipartUploadRequest; + public addFileToUpload(param0: string, param1: string, param2: string): net.gotev.uploadservice.MultipartUploadRequest; + public constructor(param0: androidcontentContext, param1: string, param2: string); + public getTaskClass(): javalangClass; + public setUtf8Charset(): net.gotev.uploadservice.MultipartUploadRequest; + public initializeIntent(param0: androidcontentIntent): void; + } + } + } +} + +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class MultipartUploadTask extends net.gotev.uploadservice.HttpUploadTask { + public static PARAM_UTF8_CHARSET: string; + public static PROPERTY_REMOTE_FILE_NAME: string; + public static PROPERTY_CONTENT_TYPE: string; + public static PROPERTY_PARAM_NAME: string; + public onBodyReady(param0: net.gotev.uploadservice.http.BodyWriter): void; + public onBytesWritten(param0: number): void; + public onSuccessfulUpload(): void; + public init(param0: net.gotev.uploadservice.UploadService, param1: androidcontentIntent): void; + public getBodyLength(): number; + public shouldContinueWriting(): boolean; + public constructor(); + } + } + } +} + +import javalangObject = java.lang.Object; +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class NameValue { + public static CREATOR: androidosParcelableCreator; + public writeToParcel(param0: androidosParcel, param1: number): void; + public static header(param0: string, param1: string): net.gotev.uploadservice.NameValue; + public equals(param0: javalangObject): boolean; + public getValue(): string; + public describeContents(): number; + public getName(): string; + public constructor(param0: string, param1: string); + } + } + } +} + +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class Placeholders { + public static ELAPSED_TIME: string; + public static UPLOAD_RATE: string; + public static PROGRESS: string; + public static UPLOADED_FILES: string; + public static TOTAL_FILES: string; + public static replace(param0: string, param1: net.gotev.uploadservice.UploadInfo): string; + public constructor(); + } + } + } +} + +import javautilLinkedHashMap = java.util.LinkedHashMap; +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class ServerResponse { + public static CREATOR: androidosParcelableCreator; + public constructor(param0: number, param1: native.Array, param2: javautilLinkedHashMap); + public writeToParcel(param0: androidosParcel, param1: number): void; + public getBodyAsString(): string; + public getHeaders(): javautilLinkedHashMap; + public constructor(param0: androidosParcel); + public getBody(): native.Array; + public describeContents(): number; + public getHttpCode(): number; + } + } + } +} + +import javaioInputStream = java.io.InputStream; +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadFile { + public path: string; + public handler: net.gotev.uploadservice.schemehandlers.SchemeHandler; + public static CREATOR: androidosParcelableCreator; + public getName(param0: androidcontentContext): string; + public getProperty(param0: string, param1: string): string; + public getStream(param0: androidcontentContext): javaioInputStream; + public writeToParcel(param0: androidosParcel, param1: number): void; + public length(param0: androidcontentContext): number; + public getPath(): string; + public constructor(param0: string); + public getContentType(param0: androidcontentContext): string; + public getProperty(param0: string): string; + public equals(param0: javalangObject): boolean; + public hashCode(): number; + public describeContents(): number; + public setProperty(param0: string, param1: string): void; + } + } + } +} + +import javalangInteger = java.lang.Integer; +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadInfo { + public static CREATOR: androidosParcelableCreator; + public getElapsedTimeString(): string; + public getUploadRate(): number; + public getUploadedBytes(): number; + public writeToParcel(param0: androidosParcel, param1: number): void; + public getProgressPercent(): number; + public getTotalBytes(): number; + public constructor(param0: string, param1: number, param2: number, param3: number, param4: number, param5: javautilList, param6: javautilList); + public getSuccessfullyUploadedFiles(): javautilArrayList; + public constructor(param0: string); + public getNotificationID(): javalangInteger; + public getUploadId(): string; + public getStartTime(): number; + public setNotificationID(param0: number): void; + public getNumberOfRetries(): number; + public getElapsedTime(): number; + public getUploadRateString(): string; + public getFilesLeft(): javautilArrayList; + public describeContents(): number; + public getTotalFiles(): number; + } + } + } +} + +import androidsupportv4appNotificationCompatAction = android.support.v4.app.NotificationCompat.Action; +import androidappPendingIntent = android.app.PendingIntent; +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadNotificationAction { + public static CREATOR: androidosParcelableCreator; + public static from(param0: androidsupportv4appNotificationCompatAction): net.gotev.uploadservice.UploadNotificationAction; + public writeToParcel(param0: androidosParcel, param1: number): void; + public equals(param0: javalangObject): boolean; + public constructor(param0: androidosParcel); + public hashCode(): number; + public describeContents(): number; + public constructor(param0: number, param1: string, param2: androidappPendingIntent); + } + } + } +} + +import androidgraphicsBitmap = android.graphics.Bitmap; +import javalangBoolean = java.lang.Boolean; +/// +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadNotificationConfig { + public static CREATOR: androidosParcelableCreator; + public setIconForAllStatuses(param0: number): net.gotev.uploadservice.UploadNotificationConfig; + public setClickIntentForAllStatuses(param0: androidappPendingIntent): net.gotev.uploadservice.UploadNotificationConfig; + public writeToParcel(param0: androidosParcel, param1: number): void; + public getNotificationChannelId(): string; + public getProgress(): net.gotev.uploadservice.UploadNotificationStatusConfig; + public getError(): net.gotev.uploadservice.UploadNotificationStatusConfig; + public addActionForAllStatuses(param0: net.gotev.uploadservice.UploadNotificationAction): net.gotev.uploadservice.UploadNotificationConfig; + public setClearOnActionForAllStatuses(param0: boolean): net.gotev.uploadservice.UploadNotificationConfig; + public isRingToneEnabled(): boolean; + public setTitleForAllStatuses(param0: string): net.gotev.uploadservice.UploadNotificationConfig; + public setRingToneEnabled(param0: javalangBoolean): net.gotev.uploadservice.UploadNotificationConfig; + public getCancelled(): net.gotev.uploadservice.UploadNotificationStatusConfig; + public setNotificationChannelId(param0: string): net.gotev.uploadservice.UploadNotificationConfig; + public constructor(); + public getCompleted(): net.gotev.uploadservice.UploadNotificationStatusConfig; + public setIconColorForAllStatuses(param0: number): net.gotev.uploadservice.UploadNotificationConfig; + public constructor(param0: androidosParcel); + public describeContents(): number; + public setLargeIconForAllStatuses(param0: androidgraphicsBitmap): net.gotev.uploadservice.UploadNotificationConfig; + } + } + } +} + +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadNotificationStatusConfig { + public title: string; + public message: string; + public autoClear: boolean; + public iconResourceID: number; + public largeIcon: androidgraphicsBitmap; + public iconColorResourceID: number; + public clickIntent: androidappPendingIntent; + public clearOnAction: boolean; + public actions: javautilArrayList; + public static CREATOR: androidosParcelableCreator; + public writeToParcel(param0: androidosParcel, param1: number): void; + public constructor(param0: androidosParcel); + public describeContents(): number; + public constructor(); + } + } + } +} + +/// +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export abstract class UploadRequest { + public context: androidcontentContext; + public params: net.gotev.uploadservice.UploadTaskParameters; + public delegate: net.gotev.uploadservice.UploadStatusDelegate; + public setAutoDeleteFilesAfterSuccessfulUpload(param0: boolean): net.gotev.uploadservice.UploadRequest; + public constructor(param0: androidcontentContext, param1: string, param2: string); + public startUpload(): string; + public setNotificationConfig(param0: net.gotev.uploadservice.UploadNotificationConfig): net.gotev.uploadservice.UploadRequest; + public setDelegate(param0: net.gotev.uploadservice.UploadStatusDelegate): net.gotev.uploadservice.UploadRequest; + public self(): net.gotev.uploadservice.UploadRequest; + public getTaskClass(): javalangClass; + public initializeIntent(param0: androidcontentIntent): void; + public setMaxRetries(param0: number): net.gotev.uploadservice.UploadRequest; + } + } + } +} + +import androidosIBinder = android.os.IBinder; +import androidappNotification = android.app.Notification; +/// +/// +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadService { + public static UPLOAD_POOL_SIZE: number; + public static KEEP_ALIVE_TIME_IN_SECONDS: number; + public static IDLE_TIMEOUT: number; + public static EXECUTE_IN_FOREGROUND: boolean; + public static NAMESPACE: string; + public static HTTP_STACK: net.gotev.uploadservice.http.HttpStack; + public static BUFFER_SIZE: number; + public static INITIAL_RETRY_WAIT_TIME: number; + public static BACKOFF_MULTIPLIER: number; + public static MAX_RETRY_WAIT_TIME: number; + public static UPLOAD_NOTIFICATION_BASE_ID: number; + public static PROGRESS_REPORT_INTERVAL: number; + public static PARAM_TASK_PARAMETERS: string; + public static PARAM_TASK_CLASS: string; + public static PARAM_BROADCAST_DATA: string; + public onStartCommand(param0: androidcontentIntent, param1: number, param2: number): number; + public static stop(param0: androidcontentContext): boolean; + public holdForegroundNotification(param0: string, param1: androidappNotification): boolean; + public static stop(param0: androidcontentContext, param1: boolean): boolean; + public constructor(); + public static getTaskList(): javautilList; + public taskCompleted(param0: string): void; + public onBind(param0: androidcontentIntent): androidosIBinder; + public static stopAllUploads(): void; + public static getActionBroadcast(): string; + public onCreate(): void; + public onDestroy(): void; + public static getActionUpload(): string; + public static setUploadStatusDelegate(param0: string, param1: net.gotev.uploadservice.UploadStatusDelegate): void; + public static getUploadStatusDelegate(param0: string): net.gotev.uploadservice.UploadStatusDelegate; + public static stopUpload(param0: string): void; + } + } + } +} + +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadServiceBroadcastReceiver { + public register(param0: androidcontentContext): void; + public onProgress(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + public onCancelled(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + public onError(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse, param3: javalangException): void; + public onReceive(param0: androidcontentContext, param1: androidcontentIntent): void; + public unregister(param0: androidcontentContext): void; + public onCompleted(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse): void; + public shouldAcceptEventFrom(param0: net.gotev.uploadservice.UploadInfo): boolean; + public constructor(); + } + } + } +} + +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadServiceSingleBroadcastReceiver extends net.gotev.uploadservice.UploadServiceBroadcastReceiver { + public constructor(param0: net.gotev.uploadservice.UploadStatusDelegate); + public onProgress(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + public setUploadID(param0: string): void; + public onCancelled(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + public onError(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse, param3: javalangException): void; + public onCompleted(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse): void; + public shouldAcceptEventFrom(param0: net.gotev.uploadservice.UploadInfo): boolean; + public constructor(); + } + } + } +} + +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadStatusDelegate { + /** + * Constructs a new instance of the net.gotev.uploadservice.UploadStatusDelegate interface with the provided implementation. + */ + public constructor(implementation: { + onProgress(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + onError(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse, param3: javalangException): void; + onCompleted(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse): void; + onCancelled(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + }); + public onProgress(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + public onCancelled(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo): void; + public onError(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse, param3: javalangException): void; + public onCompleted(param0: androidcontentContext, param1: net.gotev.uploadservice.UploadInfo, param2: net.gotev.uploadservice.ServerResponse): void; + } + } + } +} + +/// +/// +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export abstract class UploadTask { + public static TASK_COMPLETED_SUCCESSFULLY: number; + public static EMPTY_RESPONSE: native.Array; + public service: net.gotev.uploadservice.UploadService; + public params: net.gotev.uploadservice.UploadTaskParameters; + public shouldContinue: boolean; + public totalBytes: number; + public uploadedBytes: number; + public broadcastProgress(param0: number, param1: number): void; + public broadcastCompleted(param0: net.gotev.uploadservice.ServerResponse): void; + public setLastProgressNotificationTime(param0: number): net.gotev.uploadservice.UploadTask; + public addAllFilesToSuccessfullyUploadedFiles(): void; + public constructor(); + public addSuccessfullyUploadedFile(param0: net.gotev.uploadservice.UploadFile): void; + public run(): void; + public setNotificationId(param0: number): net.gotev.uploadservice.UploadTask; + public onSuccessfulUpload(): void; + public getSuccessfullyUploadedFiles(): javautilList; + public cancel(): void; + public upload(): void; + public init(param0: net.gotev.uploadservice.UploadService, param1: androidcontentIntent): void; + public broadcastCancelled(): void; + } + } + } +} + +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export class UploadTaskParameters { + public id: string; + public serverUrl: string; + public autoDeleteSuccessfullyUploadedFiles: boolean; + public notificationConfig: net.gotev.uploadservice.UploadNotificationConfig; + public files: javautilArrayList; + public static CREATOR: androidosParcelableCreator; + public setMaxRetries(param0: number): net.gotev.uploadservice.UploadTaskParameters; + public writeToParcel(param0: androidosParcel, param1: number): void; + public describeContents(): number; + public getMaxRetries(): number; + public constructor(); + } + } + } +} + +/// +declare module net { + export module gotev { + export module uploadservice { + export module http { + export abstract class BodyWriter { + public write(param0: native.Array): void; + public constructor(); + public flush(): void; + public writeStream(param0: javaioInputStream, param1: net.gotev.uploadservice.http.BodyWriter.OnStreamWriteListener): void; + public write(param0: native.Array, param1: number): void; + } + export module BodyWriter { + export class OnStreamWriteListener { + /** + * Constructs a new instance of the net.gotev.uploadservice.http.BodyWriter$OnStreamWriteListener interface with the provided implementation. + */ + public constructor(implementation: { + shouldContinueWriting(): boolean; + onBytesWritten(param0: number): void; + }); + public onBytesWritten(param0: number): void; + public shouldContinueWriting(): boolean; + } + } + } + } + } +} + +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module http { + export class HttpConnection { + /** + * Constructs a new instance of the net.gotev.uploadservice.http.HttpConnection interface with the provided implementation. + */ + public constructor(implementation: { + setHeaders(param0: javautilList): net.gotev.uploadservice.http.HttpConnection; + setTotalBodyBytes(param0: number, param1: boolean): net.gotev.uploadservice.http.HttpConnection; + getResponse(param0: net.gotev.uploadservice.http.HttpConnection.RequestBodyDelegate): net.gotev.uploadservice.ServerResponse; + close(): void; + }); + public setTotalBodyBytes(param0: number, param1: boolean): net.gotev.uploadservice.http.HttpConnection; + public close(): void; + public getResponse(param0: net.gotev.uploadservice.http.HttpConnection.RequestBodyDelegate): net.gotev.uploadservice.ServerResponse; + public setHeaders(param0: javautilList): net.gotev.uploadservice.http.HttpConnection; + } + export module HttpConnection { + export class RequestBodyDelegate { + /** + * Constructs a new instance of the net.gotev.uploadservice.http.HttpConnection$RequestBodyDelegate interface with the provided implementation. + */ + public constructor(implementation: { + onBodyReady(param0: net.gotev.uploadservice.http.BodyWriter): void; + }); + public onBodyReady(param0: net.gotev.uploadservice.http.BodyWriter): void; + } + } + } + } + } +} + +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module http { + export class HttpStack { + /** + * Constructs a new instance of the net.gotev.uploadservice.http.HttpStack interface with the provided implementation. + */ + public constructor(implementation: { + createNewConnection(param0: string, param1: string): net.gotev.uploadservice.http.HttpConnection; + }); + public createNewConnection(param0: string, param1: string): net.gotev.uploadservice.http.HttpConnection; + } + } + } + } +} + +import javaioOutputStream = java.io.OutputStream; +/// +declare module net { + export module gotev { + export module uploadservice { + export module http { + export module impl { + export class HurlBodyWriter extends net.gotev.uploadservice.http.BodyWriter { + public constructor(); + public flush(): void; + public write(param0: native.Array): void; + public write(param0: native.Array, param1: number): void; + public constructor(param0: javaioOutputStream); + } + } + } + } + } +} + +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module http { + export module impl { + export class HurlStack { + public constructor(param0: boolean, param1: boolean, param2: number, param3: number); + public constructor(); + public createNewConnection(param0: string, param1: string): net.gotev.uploadservice.http.HttpConnection; + } + } + } + } + } +} + +/// +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module http { + export module impl { + export class HurlStackConnection { + public getResponse(param0: net.gotev.uploadservice.http.HttpConnection.RequestBodyDelegate): net.gotev.uploadservice.ServerResponse; + public close(): void; + public constructor(param0: string, param1: string, param2: boolean, param3: boolean, param4: number, param5: number); + public setHeaders(param0: javautilList): net.gotev.uploadservice.http.HttpConnection; + public setTotalBodyBytes(param0: number, param1: boolean): net.gotev.uploadservice.http.HttpConnection; + } + } + } + } + } +} + +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module schemehandlers { + export class ContentSchemeHandler { + public init(param0: string): void; + public getInputStream(param0: androidcontentContext): javaioInputStream; + public getContentType(param0: androidcontentContext): string; + public getLength(param0: androidcontentContext): number; + public getName(param0: androidcontentContext): string; + } + } + } + } +} + +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module schemehandlers { + export class FileSchemeHandler { + public init(param0: string): void; + public getInputStream(param0: androidcontentContext): javaioInputStream; + public getContentType(param0: androidcontentContext): string; + public getLength(param0: androidcontentContext): number; + public getName(param0: androidcontentContext): string; + } + } + } + } +} + +/// +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module schemehandlers { + export class SchemeHandler { + /** + * Constructs a new instance of the net.gotev.uploadservice.schemehandlers.SchemeHandler interface with the provided implementation. + */ + public constructor(implementation: { + init(param0: string): void; + getLength(param0: androidcontentContext): number; + getInputStream(param0: androidcontentContext): javaioInputStream; + getContentType(param0: androidcontentContext): string; + getName(param0: androidcontentContext): string; + }); + public init(param0: string): void; + public getInputStream(param0: androidcontentContext): javaioInputStream; + public getContentType(param0: androidcontentContext): string; + public getLength(param0: androidcontentContext): number; + public getName(param0: androidcontentContext): string; + } + } + } + } +} + +/// +/// +declare module net { + export module gotev { + export module uploadservice { + export module schemehandlers { + export class SchemeHandlerFactory { + public get(param0: string): net.gotev.uploadservice.schemehandlers.SchemeHandler; + public static getInstance(): net.gotev.uploadservice.schemehandlers.SchemeHandlerFactory; + public isSupported(param0: string): boolean; + } + export module SchemeHandlerFactory { + export class LazyHolder { + } + } + } + } + } +} + From b4d4435affd02aecfdd6812547ba8e416f7299e6 Mon Sep 17 00:00:00 2001 From: Dick Smith Date: Mon, 23 Apr 2018 12:35:16 -0400 Subject: [PATCH 2/5] Per request, adding `responseCode` to `ResultEventData` Add type-checking to Error, Result, and Progress payloads. Convert tabs to spaces in `background-http.ios.ts` to be consistent with rest of repo --- src/background-http.android.ts | 27 +- src/background-http.ios.ts | 699 +++++++++++++++++---------------- src/index.d.ts | 4 +- 3 files changed, 381 insertions(+), 349 deletions(-) diff --git a/src/background-http.android.ts b/src/background-http.android.ts index 7949656..946feb9 100644 --- a/src/background-http.android.ts +++ b/src/background-http.android.ts @@ -20,7 +20,12 @@ function onProgressReceiverProgress(context: Context, uploadInfo: UploadInfo) { task.setTotalUpload(totalBytes); task.setUpload(currentBytes); task.setStatus("uploading"); - task.notify({ eventName: "progress", object: task, currentBytes: currentBytes, totalBytes: totalBytes }); + task.notify({ + eventName: "progress", + object: task, + currentBytes: currentBytes, + totalBytes: totalBytes + }); } function onProgressReceiverCancelled(context: Context, uploadInfo: UploadInfo) { @@ -34,7 +39,7 @@ function onProgressReceiverError(context: Context, uploadInfo: UploadInfo, respo const uploadId = uploadInfo.getUploadId(); const task = Task.fromId(uploadId); task.setStatus("error"); - task.notify({ + task.notify({ eventName: "error", object: task, error, @@ -42,7 +47,7 @@ function onProgressReceiverError(context: Context, uploadInfo: UploadInfo, respo }); } -function onProgressReceiverCompleted(context: Context, uploadInfo: UploadInfo, serverResponse: ServerResponse) { +function onProgressReceiverCompleted(context: Context, uploadInfo: UploadInfo, response: ServerResponse) { const uploadId = uploadInfo.getUploadId(); const task = Task.fromId(uploadId); @@ -54,9 +59,19 @@ function onProgressReceiverCompleted(context: Context, uploadInfo: UploadInfo, s task.setTotalUpload(totalUpload); task.setStatus("complete"); - task.notify({ eventName: "progress", object: task, currentBytes: totalUpload, totalBytes: totalUpload }); - task.notify({ eventName: "responded", object: task, data: serverResponse.getBodyAsString() }); - task.notify({ eventName: "complete", object: task, response: serverResponse }); + task.notify({ + eventName: "progress", + object: task, + currentBytes: totalUpload, + totalBytes: totalUpload + }); + task.notify({ + eventName: "responded", + object: task, + data: response.getBodyAsString(), + responseCode: response && typeof response.getHttpCode === 'function' ? response.getHttpCode() : -1 + }); + task.notify({ eventName: "complete", object: task, response }); } function initializeProgressReceiver() { diff --git a/src/background-http.ios.ts b/src/background-http.ios.ts index cec432d..74663b6 100644 --- a/src/background-http.ios.ts +++ b/src/background-http.ios.ts @@ -7,361 +7,376 @@ const main_queue = dispatch_get_current_queue(); class BackgroundUploadDelegate extends NSObject implements NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate { - static ObjCProtocols = [NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate]; - - // NSURLSessionDelegate - URLSessionDidBecomeInvalidWithError(session, error) { - //console.log("URLSessionDidBecomeInvalidWithError:"); - //console.log(" - session: " + session); - //console.log(" - error: " + error); - } - - URLSessionDidReceiveChallengeCompletionHandler(session, challenge, comlpetionHandler) { - //console.log("URLSessionDidFinishEventsForBackgroundURLSession: " + session + " " + challenge); - const disposition = null; - const credential = null; - comlpetionHandler(disposition, credential); - } - - URLSessionDidFinishEventsForBackgroundURLSession(session) { - //console.log("URLSessionDidFinishEventsForBackgroundURLSession: " + session); - } - - // NSURLSessionTaskDelegate - URLSessionTaskDidCompleteWithError(session: NSURLSession, nsTask: NSURLSessionTask, error: NSError) { - dispatch_async(main_queue, () => { - const task = Task.getTask(session, nsTask); - if (task._fileToCleanup) { - const fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); - fileManager.removeItemAtPathError(task._fileToCleanup); - } - if (error) { - task.notifyPropertyChange("status", task.status); - task.notify({ - eventName: "error", - object: task, - error, - responseCode: nsTask && nsTask.response ? (nsTask.response).statusCode : -1 - }); - } else { - task.notifyPropertyChange("upload", task.upload); - task.notifyPropertyChange("totalUpload", task.totalUpload); - task.notify({ eventName: "progress", object: task, currentBytes: nsTask.countOfBytesSent, totalBytes: nsTask.countOfBytesExpectedToSend }); - task.notify({ eventName: "complete", object: task }); - Task._tasks.delete(nsTask); - } - }); - } - - URLSessionTaskDidReceiveChallengeCompletionHandler(session, task, challenge, completionHandler) { - //console.log("URLSessionTaskDidReceiveChallengeCompletionHandler: " + session + " " + task + " " + challenge); - const disposition = null; - const credential = null; - completionHandler(disposition, credential); - } - - URLSessionTaskDidSendBodyDataTotalBytesSentTotalBytesExpectedToSend(nsSession: NSURLSession, nsTask: NSURLSessionTask, data, sent: number, expectedTotal: number) { - dispatch_async(main_queue, () => { - const task = Task.getTask(nsSession, nsTask); - //console.log("notifyPropertyChange: upload"); - task.notifyPropertyChange("upload", task.upload); - //console.log("notifyPropertyChange: totalUpload"); - task.notifyPropertyChange("totalUpload", task.totalUpload); - task.notify({ eventName: "progress", object: task, currentBytes: sent, totalBytes: expectedTotal }); - }); - } - - URLSessionTaskNeedNewBodyStream(session, task, need) { - //console.log("URLSessionTaskNeedNewBodyStream"); - } - - URLSessionTaskWillPerformHTTPRedirectionNewRequestCompletionHandler(session, task, redirect, request, completionHandler) { - //console.log("URLSessionTaskWillPerformHTTPRedirectionNewRequestCompletionHandler"); - completionHandler(request); - } - - // NSURLSessionDataDelegate - URLSessionDataTaskDidReceiveResponseCompletionHandler(session, dataTask, response, completionHandler) { - //console.log("URLSessionDataTaskDidReceiveResponseCompletionHandler"); - const disposition = null; - completionHandler(disposition); - } - - URLSessionDataTaskDidBecomeDownloadTask(session, dataTask, downloadTask) { - //console.log("URLSessionDataTaskDidBecomeDownloadTask"); - } - - URLSessionDataTaskDidReceiveData(session, dataTask, data) { - dispatch_async(main_queue, () => { - //console.log("URLSessionDataTaskDidReceiveData"); - // we have a response in the data... - const jsTask = Task.getTask(session, dataTask); - const jsonString = NSString.alloc().initWithDataEncoding(data, NSUTF8StringEncoding); - - jsTask.notify({ eventName: "responded", object: jsTask, data: jsonString.toString() }); - }); - } - - URLSessionDataTaskWillCacheResponseCompletionHandler() { - //console.log("URLSessionDataTaskWillCacheResponseCompletionHandler"); - } - - // NSURLSessionDownloadDelegate - URLSessionDownloadTaskDidResumeAtOffsetExpectedTotalBytes(session, task, offset, expects) { - //console.log("URLSessionDownloadTaskDidResumeAtOffsetExpectedTotalBytes"); - } - - URLSessionDownloadTaskDidWriteDataTotalBytesWrittenTotalBytesExpectedToWrite(session, task, data, written, expected) { - //console.log("URLSessionDownloadTaskDidWriteDataTotalBytesWrittenTotalBytesExpectedToWrite"); - } - - URLSessionDownloadTaskDidFinishDownloadingToURL(session, task, url) { - //console.log("URLSessionDownloadTaskDidFinishDownloadingToURL"); - } + static ObjCProtocols = [NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate]; + + // NSURLSessionDelegate + URLSessionDidBecomeInvalidWithError(session, error) { + //console.log("URLSessionDidBecomeInvalidWithError:"); + //console.log(" - session: " + session); + //console.log(" - error: " + error); + } + + URLSessionDidReceiveChallengeCompletionHandler(session, challenge, comlpetionHandler) { + //console.log("URLSessionDidFinishEventsForBackgroundURLSession: " + session + " " + challenge); + const disposition = null; + const credential = null; + comlpetionHandler(disposition, credential); + } + + URLSessionDidFinishEventsForBackgroundURLSession(session) { + //console.log("URLSessionDidFinishEventsForBackgroundURLSession: " + session); + } + + // NSURLSessionTaskDelegate + URLSessionTaskDidCompleteWithError(session: NSURLSession, nsTask: NSURLSessionTask, error: NSError) { + dispatch_async(main_queue, () => { + const task = Task.getTask(session, nsTask); + if (task._fileToCleanup) { + const fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); + fileManager.removeItemAtPathError(task._fileToCleanup); + } + if (error) { + task.notifyPropertyChange("status", task.status); + task.notify({ + eventName: "error", + object: task, + error, + responseCode: nsTask && nsTask.response ? (nsTask.response).statusCode : -1 + }); + } else { + task.notifyPropertyChange("upload", task.upload); + task.notifyPropertyChange("totalUpload", task.totalUpload); + task.notify({ + eventName: "progress", + object: task, + currentBytes: nsTask.countOfBytesSent, + totalBytes: nsTask.countOfBytesExpectedToSend + }); + task.notify({ eventName: "complete", object: task }); + Task._tasks.delete(nsTask); + } + }); + } + + URLSessionTaskDidReceiveChallengeCompletionHandler(session, task, challenge, completionHandler) { + //console.log("URLSessionTaskDidReceiveChallengeCompletionHandler: " + session + " " + task + " " + challenge); + const disposition = null; + const credential = null; + completionHandler(disposition, credential); + } + + URLSessionTaskDidSendBodyDataTotalBytesSentTotalBytesExpectedToSend(nsSession: NSURLSession, nsTask: NSURLSessionTask, data, sent: number, expectedTotal: number) { + dispatch_async(main_queue, () => { + const task = Task.getTask(nsSession, nsTask); + //console.log("notifyPropertyChange: upload"); + task.notifyPropertyChange("upload", task.upload); + //console.log("notifyPropertyChange: totalUpload"); + task.notifyPropertyChange("totalUpload", task.totalUpload); + task.notify({ + eventName: "progress", + object: task, + currentBytes: sent, + totalBytes: expectedTotal + }); + }); + } + + URLSessionTaskNeedNewBodyStream(session, task, need) { + //console.log("URLSessionTaskNeedNewBodyStream"); + } + + URLSessionTaskWillPerformHTTPRedirectionNewRequestCompletionHandler(session, task, redirect, request, completionHandler) { + //console.log("URLSessionTaskWillPerformHTTPRedirectionNewRequestCompletionHandler"); + completionHandler(request); + } + + // NSURLSessionDataDelegate + URLSessionDataTaskDidReceiveResponseCompletionHandler(session, dataTask, response, completionHandler) { + //console.log("URLSessionDataTaskDidReceiveResponseCompletionHandler"); + const disposition = null; + completionHandler(disposition); + } + + URLSessionDataTaskDidBecomeDownloadTask(session, dataTask, downloadTask) { + //console.log("URLSessionDataTaskDidBecomeDownloadTask"); + } + + URLSessionDataTaskDidReceiveData(session: NSURLSession, dataTask: NSURLSessionDataTask, data: NSData) { + dispatch_async(main_queue, () => { + //console.log("URLSessionDataTaskDidReceiveData"); + // we have a response in the data... + const jsTask = Task.getTask(session, dataTask); + const jsonString = NSString.alloc().initWithDataEncoding(data, NSUTF8StringEncoding); + + jsTask.notify({ + eventName: "responded", + object: jsTask, + data: jsonString.toString(), + responseCode: nsTask && nsTask.response ? (nsTask.response).statusCode : -1 + }); + }); + } + + URLSessionDataTaskWillCacheResponseCompletionHandler() { + //console.log("URLSessionDataTaskWillCacheResponseCompletionHandler"); + } + + // NSURLSessionDownloadDelegate + URLSessionDownloadTaskDidResumeAtOffsetExpectedTotalBytes(session, task, offset, expects) { + //console.log("URLSessionDownloadTaskDidResumeAtOffsetExpectedTotalBytes"); + } + + URLSessionDownloadTaskDidWriteDataTotalBytesWrittenTotalBytesExpectedToWrite(session, task, data, written, expected) { + //console.log("URLSessionDownloadTaskDidWriteDataTotalBytesWrittenTotalBytesExpectedToWrite"); + } + + URLSessionDownloadTaskDidFinishDownloadingToURL(session, task, url) { + //console.log("URLSessionDownloadTaskDidFinishDownloadingToURL"); + } } class Session implements common.Session { - // TODO: Create a mechanism to clean sessions from the cache that have all their tasks completed, canceled or errored out. - private static _sessions: { [id: string]: Session } = {}; - - private _session: NSURLSession; - - constructor(id: string) { - const delegate = BackgroundUploadDelegate.alloc().init(); - const configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(id); - this._session = NSURLSession.sessionWithConfigurationDelegateDelegateQueue(configuration, delegate, null); - } - - get ios(): any { - return this._session; - } - - - public uploadFile(fileUri: string, options: common.Request): common.Task { - if (!fileUri) { - throw new Error("File must be provided."); - } - - const url = NSURL.URLWithString(options.url); - const request = NSMutableURLRequest.requestWithURL(url); - - const headers = options.headers; - if (headers) { - for (let header in headers) { - const value = headers[header]; - if (value !== null && value !== void 0) { - request.setValueForHTTPHeaderField(value.toString(), header); - } - } - } - - if (options.method) { - request.HTTPMethod = options.method; - } - - let fileURL: NSURL; - if (fileUri.substr(0, 7) === "file://") { - // File URI in string format - fileURL = NSURL.URLWithString(fileUri); - } else if (fileUri.charAt(0) === "/") { - // Absolute path with leading slash - fileURL = NSURL.fileURLWithPath(fileUri); - } - - const newTask = this._session.uploadTaskWithRequestFromFile(request, fileURL); - newTask.taskDescription = options.description; - newTask.resume(); - const retTask: common.Task = Task.getTask(this._session, newTask); - return retTask; - } - public multipartUpload(params: any[], options: any): common.Task { - const MPF = new MultiMultiPartForm(); - for (let i = 0; i < params.length; i++) { - const curParam = params[i]; - if (typeof curParam.name === 'undefined') { - throw new Error("You must have a `name` value"); - } - - if (curParam.filename) { - const destFileName = curParam.destFilename || curParam.filename.substring(curParam.filename.lastIndexOf('/') + 1, curParam.filename.length); - MPF.appendParam(curParam.name, null, curParam.filename, curParam.mimeType, destFileName); - } else { - MPF.appendParam(curParam.name, curParam.value); - } - } - const header = MPF.getHeader(); - const uploadFile = MPF.generateFile(); - - if (!options.headers) { - options.headers = {}; - } - options.headers['Content-Type'] = header['Content-Type']; - - const task = this.uploadFile(uploadFile, options); - - // Tag the file to be deleted and cleanup after upload - (task)._fileToCleanup = uploadFile; - return task; - } - static getSession(id: string): common.Session { - let jsSession = Session._sessions[id]; - if (jsSession) { - return jsSession; - } - jsSession = new Session(id); - Session._sessions[id] = jsSession; - return jsSession; - } + // TODO: Create a mechanism to clean sessions from the cache that have all their tasks completed, canceled or errored out. + private static _sessions: { [id: string]: Session } = {}; + + private _session: NSURLSession; + + constructor(id: string) { + const delegate = BackgroundUploadDelegate.alloc().init(); + const configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier(id); + this._session = NSURLSession.sessionWithConfigurationDelegateDelegateQueue(configuration, delegate, null); + } + + get ios(): any { + return this._session; + } + + + public uploadFile(fileUri: string, options: common.Request): common.Task { + if (!fileUri) { + throw new Error("File must be provided."); + } + + const url = NSURL.URLWithString(options.url); + const request = NSMutableURLRequest.requestWithURL(url); + + const headers = options.headers; + if (headers) { + for (let header in headers) { + const value = headers[header]; + if (value !== null && value !== void 0) { + request.setValueForHTTPHeaderField(value.toString(), header); + } + } + } + + if (options.method) { + request.HTTPMethod = options.method; + } + + let fileURL: NSURL; + if (fileUri.substr(0, 7) === "file://") { + // File URI in string format + fileURL = NSURL.URLWithString(fileUri); + } else if (fileUri.charAt(0) === "/") { + // Absolute path with leading slash + fileURL = NSURL.fileURLWithPath(fileUri); + } + + const newTask = this._session.uploadTaskWithRequestFromFile(request, fileURL); + newTask.taskDescription = options.description; + newTask.resume(); + const retTask: common.Task = Task.getTask(this._session, newTask); + return retTask; + } + public multipartUpload(params: any[], options: any): common.Task { + const MPF = new MultiMultiPartForm(); + for (let i = 0; i < params.length; i++) { + const curParam = params[i]; + if (typeof curParam.name === 'undefined') { + throw new Error("You must have a `name` value"); + } + + if (curParam.filename) { + const destFileName = curParam.destFilename || curParam.filename.substring(curParam.filename.lastIndexOf('/') + 1, curParam.filename.length); + MPF.appendParam(curParam.name, null, curParam.filename, curParam.mimeType, destFileName); + } else { + MPF.appendParam(curParam.name, curParam.value); + } + } + const header = MPF.getHeader(); + const uploadFile = MPF.generateFile(); + + if (!options.headers) { + options.headers = {}; + } + options.headers['Content-Type'] = header['Content-Type']; + + const task = this.uploadFile(uploadFile, options); + + // Tag the file to be deleted and cleanup after upload + (task)._fileToCleanup = uploadFile; + return task; + } + static getSession(id: string): common.Session { + let jsSession = Session._sessions[id]; + if (jsSession) { + return jsSession; + } + jsSession = new Session(id); + Session._sessions[id] = jsSession; + return jsSession; + } } class Task extends Observable { - public static _tasks = new Map(); - - public _fileToCleanup: string; - private _task: NSURLSessionTask; - private _session: NSURLSession; - - constructor(nsSession: NSURLSession, nsTask: NSURLSessionTask) { - super(); - this._task = nsTask; - this._session = nsSession; - } - - get ios(): any { - return this._task; - } - - get description(): string { - return this._task.taskDescription; - } - - get upload(): number { - return this._task.countOfBytesSent; - } - - get totalUpload(): number { - return this._task.countOfBytesExpectedToSend; - } - - get status(): string { - if (this._task.error) { - return "error"; - } - switch (this._task.state) { - case NSURLSessionTaskState.Running: return "uploading"; - case NSURLSessionTaskState.Completed: return "complete"; - case NSURLSessionTaskState.Canceling: return "error"; - case NSURLSessionTaskState.Suspended: return "pending"; - } - } - - public static getTask(nsSession: NSURLSession, nsTask: NSURLSessionTask): Task { - let task = Task._tasks.get(nsTask); - if (task) { - return task; - } - - task = new Task(nsSession, nsTask); - Task._tasks.set(nsTask, task); - - return task; - } - public cancel(): void { - this._task.cancel(); - } + public static _tasks = new Map(); + + public _fileToCleanup: string; + private _task: NSURLSessionTask; + private _session: NSURLSession; + + constructor(nsSession: NSURLSession, nsTask: NSURLSessionTask) { + super(); + this._task = nsTask; + this._session = nsSession; + } + + get ios(): any { + return this._task; + } + + get description(): string { + return this._task.taskDescription; + } + + get upload(): number { + return this._task.countOfBytesSent; + } + + get totalUpload(): number { + return this._task.countOfBytesExpectedToSend; + } + + get status(): string { + if (this._task.error) { + return "error"; + } + switch (this._task.state) { + case NSURLSessionTaskState.Running: return "uploading"; + case NSURLSessionTaskState.Completed: return "complete"; + case NSURLSessionTaskState.Canceling: return "error"; + case NSURLSessionTaskState.Suspended: return "pending"; + } + } + + public static getTask(nsSession: NSURLSession, nsTask: NSURLSessionTask): Task { + let task = Task._tasks.get(nsTask); + if (task) { + return task; + } + + task = new Task(nsSession, nsTask); + Task._tasks.set(nsTask, task); + + return task; + } + public cancel(): void { + this._task.cancel(); + } } export function session(id: string): common.Session { - return Session.getSession(id); + return Session.getSession(id); } class MultiMultiPartForm { - private boundary: string; - private header: any; - private fileCount: number; - private fields: Array; - - constructor() { - this.clear(); - } - - public clear(): void { - this.boundary = "--------------formboundary" + Math.floor(Math.random() * 100000000000); - this.header = { "Content-Type": 'multipart/form-data; boundary=' + this.boundary }; - this.fileCount = 0; - this.fields = []; - } - - public appendParam(name: string, value: string, filename?: string, mimeType?: string, destFileName?: string): void { - // If all we are doing is passing a field, we just add it to the fields list - if (filename == null) { - this.fields.push({ name: name, value: value }); - return; - } - // Load file - mimeType = mimeType || "application/data"; - - if (filename.startsWith("~/")) { - filename = filename.replace("~/", fileSystemModule.knownFolders.currentApp().path + "/"); - } - - const finalName = destFileName || filename.substr(filename.lastIndexOf('/') + 1, filename.length); - this.fields.push({ name: name, filename: filename, destFilename: finalName, mimeType: mimeType }); - }; - - public generateFile(): string { - const CRLF = "\r\n"; - - const fileName = fileSystemModule.knownFolders.documents().path + "/temp-MPF-" + Math.floor(Math.random() * 100000000000) + ".tmp"; - - const combinedData = NSMutableData.alloc().init(); - - let results: string = ""; - let tempString: NSString; - let newData: any; - for (let i = 0; i < this.fields.length; i++) { - results += "--" + this.boundary + CRLF; - results += 'Content-Disposition: form-data; name="' + this.fields[i].name + '"'; - if (!this.fields[i].filename) { - results += CRLF + CRLF + this.fields[i].value + CRLF; - } else { - results += '; filename="' + this.fields[i].destFilename + '"'; - if (this.fields[i].mimeType) { - results += CRLF + "Content-Type: " + this.fields[i].mimeType; - } - results += CRLF + CRLF; - } - - tempString = NSString.stringWithString(results); - results = ""; - newData = tempString.dataUsingEncoding(NSUTF8StringEncoding); - combinedData.appendData(newData); - - - if (this.fields[i].filename) { - const fileData = NSData.alloc().initWithContentsOfFile(this.fields[i].filename); - combinedData.appendData(fileData); - results = CRLF; - } - - } - // Add final part of it... - results += "--" + this.boundary + "--" + CRLF; - tempString = NSString.stringWithString(results); - newData = tempString.dataUsingEncoding(NSUTF8StringEncoding); - combinedData.appendData(newData); - - - const fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); - fileManager.createFileAtPathContentsAttributes(fileName, combinedData, null); - - return fileName; - }; - - public getHeader(): string { - return this.header; - }; + private boundary: string; + private header: any; + private fileCount: number; + private fields: Array; + + constructor() { + this.clear(); + } + + public clear(): void { + this.boundary = "--------------formboundary" + Math.floor(Math.random() * 100000000000); + this.header = { "Content-Type": 'multipart/form-data; boundary=' + this.boundary }; + this.fileCount = 0; + this.fields = []; + } + + public appendParam(name: string, value: string, filename?: string, mimeType?: string, destFileName?: string): void { + // If all we are doing is passing a field, we just add it to the fields list + if (filename == null) { + this.fields.push({ name: name, value: value }); + return; + } + // Load file + mimeType = mimeType || "application/data"; + + if (filename.startsWith("~/")) { + filename = filename.replace("~/", fileSystemModule.knownFolders.currentApp().path + "/"); + } + + const finalName = destFileName || filename.substr(filename.lastIndexOf('/') + 1, filename.length); + this.fields.push({ name: name, filename: filename, destFilename: finalName, mimeType: mimeType }); + }; + + public generateFile(): string { + const CRLF = "\r\n"; + + const fileName = fileSystemModule.knownFolders.documents().path + "/temp-MPF-" + Math.floor(Math.random() * 100000000000) + ".tmp"; + + const combinedData = NSMutableData.alloc().init(); + + let results: string = ""; + let tempString: NSString; + let newData: any; + for (let i = 0; i < this.fields.length; i++) { + results += "--" + this.boundary + CRLF; + results += 'Content-Disposition: form-data; name="' + this.fields[i].name + '"'; + if (!this.fields[i].filename) { + results += CRLF + CRLF + this.fields[i].value + CRLF; + } else { + results += '; filename="' + this.fields[i].destFilename + '"'; + if (this.fields[i].mimeType) { + results += CRLF + "Content-Type: " + this.fields[i].mimeType; + } + results += CRLF + CRLF; + } + + tempString = NSString.stringWithString(results); + results = ""; + newData = tempString.dataUsingEncoding(NSUTF8StringEncoding); + combinedData.appendData(newData); + + + if (this.fields[i].filename) { + const fileData = NSData.alloc().initWithContentsOfFile(this.fields[i].filename); + combinedData.appendData(fileData); + results = CRLF; + } + + } + // Add final part of it... + results += "--" + this.boundary + "--" + CRLF; + tempString = NSString.stringWithString(results); + newData = tempString.dataUsingEncoding(NSUTF8StringEncoding); + combinedData.appendData(newData); + + + const fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); + fileManager.createFileAtPathContentsAttributes(fileName, combinedData, null); + + return fileName; + }; + + public getHeader(): string { + return this.header; + }; } diff --git a/src/index.d.ts b/src/index.d.ts index 1e94959..94fb225 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -41,6 +41,8 @@ export interface ResultEventData extends observable.EventData { * The string response of the server. */ data: string; + /** HTTP response code if response object is present, otherwise -1 */ + responseCode: number; } /** @@ -76,7 +78,7 @@ export interface Task { /** * Subscribe for a general event. * @param event The name of the event to subscribe for. - * @param The handler called when the event occure. + * @param handler The handler called when the event occure. * @event */ on(event: string, handler: (e: observable.EventData) => void): void; From b2f214aee3209b8c0f2990ebd3e77f38dc749c5d Mon Sep 17 00:00:00 2001 From: Dick Smith Date: Mon, 23 Apr 2018 12:51:55 -0400 Subject: [PATCH 3/5] Per Request, creating interface for CompleteEventData Adding `responseCode` to CompleteEventData Breaking for Android: Android originally returned the response here (undocumented behaviour), while iOS did not, so now only the code will be returned --- src/background-http.android.ts | 6 +++++- src/background-http.ios.ts | 6 +++++- src/index.d.ts | 5 +++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/background-http.android.ts b/src/background-http.android.ts index 946feb9..86670ab 100644 --- a/src/background-http.android.ts +++ b/src/background-http.android.ts @@ -71,7 +71,11 @@ function onProgressReceiverCompleted(context: Context, uploadInfo: UploadInfo, r data: response.getBodyAsString(), responseCode: response && typeof response.getHttpCode === 'function' ? response.getHttpCode() : -1 }); - task.notify({ eventName: "complete", object: task, response }); + task.notify({ + eventName: "complete", + object: task, + responseCode: response && typeof response.getHttpCode === 'function' ? response.getHttpCode() : -1 + }); } function initializeProgressReceiver() { diff --git a/src/background-http.ios.ts b/src/background-http.ios.ts index 74663b6..b6a821d 100644 --- a/src/background-http.ios.ts +++ b/src/background-http.ios.ts @@ -52,7 +52,11 @@ class BackgroundUploadDelegate extends NSObject implements NSURLSessionDelegate, currentBytes: nsTask.countOfBytesSent, totalBytes: nsTask.countOfBytesExpectedToSend }); - task.notify({ eventName: "complete", object: task }); + task.notify({ + eventName: "complete", + object: task, + responseCode: nsTask && nsTask.response ? (nsTask.response).statusCode : -1 + }); Task._tasks.delete(nsTask); } }); diff --git a/src/index.d.ts b/src/index.d.ts index 94fb225..20d4c2f 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -45,6 +45,11 @@ export interface ResultEventData extends observable.EventData { responseCode: number; } +export interface CompleteEventData extends observable.EventData { + /** HTTP response code if response object is present, otherwise -1 */ + responseCode: number; +} + /** * Encapsulates some information for background http transfers. */ From 517cf63297efc5e134839289bab5f486811aaa34 Mon Sep 17 00:00:00 2001 From: Dick Smith Date: Mon, 23 Apr 2018 17:05:29 -0400 Subject: [PATCH 4/5] Fix --- src/background-http.ios.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/background-http.ios.ts b/src/background-http.ios.ts index b6a821d..b46866a 100644 --- a/src/background-http.ios.ts +++ b/src/background-http.ios.ts @@ -116,7 +116,7 @@ class BackgroundUploadDelegate extends NSObject implements NSURLSessionDelegate, eventName: "responded", object: jsTask, data: jsonString.toString(), - responseCode: nsTask && nsTask.response ? (nsTask.response).statusCode : -1 + responseCode: dataTask && dataTask.response ? (dataTask.response).statusCode : -1 }); }); } From e72ce73e118003c0374dde5053ded1ba5d6324a7 Mon Sep 17 00:00:00 2001 From: Dick Smith Date: Tue, 24 Apr 2018 15:01:26 -0400 Subject: [PATCH 5/5] Add back response object for Android. --- src/background-http.android.ts | 3 ++- src/index.d.ts | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/background-http.android.ts b/src/background-http.android.ts index 86670ab..8efadbd 100644 --- a/src/background-http.android.ts +++ b/src/background-http.android.ts @@ -43,7 +43,8 @@ function onProgressReceiverError(context: Context, uploadInfo: UploadInfo, respo eventName: "error", object: task, error, - responseCode: response && typeof response.getHttpCode === 'function' ? response.getHttpCode() : -1 + responseCode: response && typeof response.getHttpCode === 'function' ? response.getHttpCode() : -1, + response }); } diff --git a/src/index.d.ts b/src/index.d.ts index 20d4c2f..b188052 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -48,6 +48,8 @@ export interface ResultEventData extends observable.EventData { export interface CompleteEventData extends observable.EventData { /** HTTP response code if response object is present, otherwise -1 */ responseCode: number; + /** Currently available for Android only */ + response?: any; // net.gotev.uploadservice.ServerResponse } /**