Completion Handler of an NSURLSessionTask does not run

259 views Asked by At

Hello I am trying to perform a simple authentication on a Java server from a swift client. The java server is an HTTPServer and its code takes a "POST" request with a Username and Password. The server returns true if the username and password are correct, and false if they are not through JSON data.

The problem I believe lies in the swift client. It does not seem to run the completion code of the task, and therefore I don't believe it is actually able to connect to the server, run on localhost. Both the client code, and the server code are shown below. Could you please tell me why the completion code wouldn't be running? And possibly give me an answer as to how to fix it?

Swift Client:

import Foundation

    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: configuration)
    let usr = "TBecker"
    let pwdCode = "TBecker"
    let params:[String: AnyObject] = [
        "User" : usr,
        "Pass" : pwdCode ]

    let url = NSURL(string:"http://localhost:8080/auth")
    let request = NSMutableURLRequest(URL: url)
    request.setValue("application/json; charset=utf-8", forHTTPHeaderField: "Content-Type")
    request.HTTPMethod = "POST"

    if (NSJSONSerialization.isValidJSONObject(params)) {
            do {
                    request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: NSJSONWritingOptions.PrettyPrinted)
            } catch {
                    print("catch failed")
            }
    }

    let task = session.dataTaskWithRequest(request, completionHandler: {data, response, error in

            if let httpResponse = response as? NSHTTPURLResponse {
                    if httpResponse.statusCode != 200 {
                            print("response was not 200: \(response)")
                            return
                    }
            }
            if (error != nil) {
                    print("error submitting request: \(error)")
                    return
            }

            // handle the data of the successful response here
            if (NSJSONSerialization.isValidJSONObject(data!)) {
                    do {
                            print("received data of some sort")
                            let result = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
                            print(result)
                    } catch {
                            print("catch failed")
                    }
            }
    })

    task.resume()

Java Server:

    public class HTTPRequestHandler {
    private static final String HOSTNAME = "localhost";
    private static final int PORT = 8080;
    private static final int BACKLOG = 1;

    private static final String HEADER_ALLOW = "Allow";
    private static final String HEADER_CONTENT_TYPE = "Content-Type";

    private static final Charset CHARSET = StandardCharsets.UTF_8;

    private static final int STATUS_OK = 200;
    private static final int STATUS_METHOD_NOT_ALLOWED = 405;

    private static final int NO_RESPONSE_LENGTH = -1;

    private static final String METHOD_POST = "POST";
    private static final String METHOD_OPTIONS = "OPTIONS";
    private static final String ALLOWED_METHODS = METHOD_POST + "," + METHOD_OPTIONS;

    public static void main(final String... args) throws IOException {
        final HttpServer server = HttpServer.create(new InetSocketAddress(HOSTNAME, PORT), BACKLOG);
        server.createContext("/auth", he -> {
            try {
                System.out.println("Request currently being handled");
                final Headers headers = he.getResponseHeaders();
                final String requestMethod = he.getRequestMethod().toUpperCase();
                switch (requestMethod) {
                    case METHOD_POST:
                        final Map<String, List<String>> requestParameters = getRequestParameters(he.getRequestURI());
                        // do something with the request parameters
                        final String success;

                        if (requestParameters.containsKey("User") && requestParameters.containsKey("Pass"))
                            if (requestParameters.get("User").equals("TBecker") && requestParameters.get("Pass").equals("TBecker")) {
                                    success = "['true']";
                            } else {
                                success = "['false']";
                            }
                        else
                            success = "['false']";
                        headers.set(HEADER_CONTENT_TYPE, String.format("application/json; charset=%s", CHARSET));
                        final byte[] rawSuccess = success.getBytes(CHARSET);
                        he.sendResponseHeaders(STATUS_OK, rawSuccess.length);
                        he.getResponseBody().write(rawSuccess);
                        break;
                    default:
                        headers.set(HEADER_ALLOW, ALLOWED_METHODS);
                        he.sendResponseHeaders(STATUS_METHOD_NOT_ALLOWED, NO_RESPONSE_LENGTH);
                        break;
                }
            } finally {
                System.out.println("request successfully handled");
                he.close();
            }
        });
        server.start();
    }

    private static Map<String, List<String>> getRequestParameters(final URI requestUri) {
        final Map<String, List<String>> requestParameters = new LinkedHashMap<>();
        final String requestQuery = requestUri.getRawQuery();
        if (requestQuery != null) {
            final String[] rawRequestParameters = requestQuery.split("[&;]", -1);
            for (final String rawRequestParameter : rawRequestParameters) {
                final String[] requestParameter = rawRequestParameter.split("=", 2);
                final String requestParameterName = decodeUrlComponent(requestParameter[0]);
                requestParameters.putIfAbsent(requestParameterName, new ArrayList<>());
                final String requestParameterValue = requestParameter.length > 1 ? decodeUrlComponent(requestParameter[1]) : null;
                requestParameters.get(requestParameterName).add(requestParameterValue);
            }
        }
        return requestParameters;
    }

    private static String decodeUrlComponent(final String urlComponent) {
        try {
            return URLDecoder.decode(urlComponent, CHARSET.name());
        } catch (final UnsupportedEncodingException ex) {
            throw new InternalError(ex);
        }
    }
}

thank you!

1

There are 1 answers

0
Jack H On BEST ANSWER

It seems like the program is terminating before the server has a chance to respond. Since I'm guessing it was a standalone app, there wasn't anything to keep it concurrently running, so probably inside a swift app itself it would keep running and not have the issue.