Skip to content

Basic NSURLSession implementation #299

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

Closed
wants to merge 1 commit into from

Conversation

danieleggert
Copy link
Contributor

I'm creating this pull request to get feedback on my implementation so far.

There are still many TODOs in the code, but it’s far along enough to evaluate the architecture and design I have chosen for this task. I’ve tried to outline quite a bit in the code itself in form of comments. Please let me know:

  • which parts need more explanation
  • which parts should be redesigned
  • which parts need more testing

The NSURLSession.swift file has a NSURLSession API implementation overview.

As for testing, I'm hoping to spend quite a bit of time on building an in-process HTTP server to better test some of the desired behaviour. Particularly when testing things such as different payloads, headers, and POST / PUT requests that's the only way to get good testing.

I'd like to split the NSURLSession+libcurl.swift file into multiple smaller files, but that'd break with the existing style. Any thoughts?

The CFURLSessionInterface.{c,h} files are very verbose in order to not expose libcurl directly. This was suggested by @phausler and @rothomp3 — but I'm not sure if this is what they were hoping for.

All unimplemented code should still be marked with NSUnimplemented() where applicable.

This does not at all try to implement so-called background session which would have
to rely on a system daemon to perform HTTP requests white the app is not running (either
suspended or terminated). Such code would have to rely on IPC and the launchd equivalent
on the platform it is running on.

// testCase(TestNSValue.allTests),
// testCase(TestNSUserDefaults.allTests),
// testCase(TestNSXMLParser.allTests),
// testCase(TestNSXMLDocument.allTests),
Copy link
Contributor

Choose a reason for hiding this comment

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

obviously these will all have to be re-enabled before merging is considered.

@danieleggert
Copy link
Contributor Author

I should note that this relies on https://github.com/apple/swift-corelibs-libdispatch — and it has an extremely rudimentary version of NSOperationQueue to support the delegate queue on NSURLSession.

CFURLSession_EasyCodeNO_CONNECTION_AVAILABLE, // CURLE_NO_CONNECTION_AVAILABLE
CFURLSession_EasyCodeSSL_PINNEDPUBKEYNOTMATCH, // CURLE_SSL_PINNEDPUBKEYNOTMATCH
CFURLSession_EasyCodeSSL_INVALIDCERTSTATUS, // CURLE_SSL_INVALIDCERTSTATUS
} CFURLSession_EasyCode;
Copy link
Contributor

Choose a reason for hiding this comment

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

it is worth noting that when porting to Linux these will not be exported in the same manner as enums on Darwin. We have numerous other examples that show the #if os(OSX) || os(iOS) re-export as constant pattern that must be done. it might be worthwhile to modify that script that generates these to generate those as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Makes sense. I’ll deal with that once libdispatch lands for Linux — until then it won’t compile either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I changed this to avoid using enum in C.

@phausler
Copy link
Contributor

per the NSOQ stub (and other dispatch usage) we are still waiting on libdispatch to completely land; hopefully before then I will have some more things for NSOQ that will give a decent implementation for something more complete than what you have so far.

@danieleggert danieleggert force-pushed the urlsession branch 3 times, most recently from f9dd2c3 to 85abca1 Compare April 1, 2016 15:58
@danieleggert danieleggert force-pushed the urlsession branch 2 times, most recently from 9d087d0 to 63a7b48 Compare April 4, 2016 17:46
@danieleggert
Copy link
Contributor Author

Question: What changes should be done on this before it can be merged back into master?
One thing I'm aware of: this needs libdispatch, and that's not there, yet, on Linux. What’s a reasonable workaround? Or should we wait?

Also, I'd like feedback on the fact that NSURLSession.swift and NSURLSession+libcurl.swift are now 2090 and 1741 lines respectively, and that it may make sense to break these into multiple smaller files. Any thoughts?

@danieleggert danieleggert changed the title [WIP] Basic NSURLSession implementation Basic NSURLSession implementation Apr 4, 2016
@parkera
Copy link
Contributor

parkera commented Apr 4, 2016

We're still working on dispatch; it's certainly the plan for it to be available. We should proceed as if it'll be there in the end.

I'm ok with splitting implementation into multiple files as well.

Thanks for your work on this @danieleggert.

@danieleggert
Copy link
Contributor Author

I’ve split it into these files

NSURLSession.swift
NSURLSessionConfiguration.swift
NSURLSessionDelegate.swift
NSURLSessionTask.swift
Configuration.swift
EasyHandle.swift
HTTPBodySource.swift
HTTPMessage.swift
MultiHandle.swift
TaskRegistry.swift
TransferState.swift
libcurlHelpers.swift

@@ -2150,6 +2226,7 @@
r,
r,
);
OTHER_SWIFT_FLAGS = "-DDEPLOYMENT_ENABLE_LIBDISPATCH";
Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably leave this out until everything is ready to go right?

@parkera
Copy link
Contributor

parkera commented Apr 6, 2016

I'd like to double check a few things:

  1. Is this disabled by default on Linux, since dispatch is not yet integrated?
  2. I'm unsure about enabling by default on Darwin. I suppose that's fine, since it's for our own purposes.
  3. The tests should only run if it's enabled (obviously).
  4. Can we remove some of the scheme settings?

Once we're set, we'll squash merge this in so we can work on it iteratively after that (including enabling on Linux).

@danieleggert
Copy link
Contributor Author

@parkera This all assumes that libdispatch is available on Linux — we’ll have to hold off until then. I’ll do a few more tweaks to this tomorrow and the day after and then squash everything into a single commit.

One option would be to add the old version of NSURLSession.swift as NSURLSession+Unimplemented.swift and use that one for Linux. Thoughts?

@danieleggert danieleggert force-pushed the urlsession branch 3 times, most recently from 6d3cb17 to 836b865 Compare April 6, 2016 21:53
@danieleggert
Copy link
Contributor Author

It’s all squashed into a single commit now, but I might keep working on this.

@danieleggert
Copy link
Contributor Author

Note that this includes #306 and #287 — those should be merged first, or this one changed if they’re not to be merged.

@danieleggert danieleggert force-pushed the urlsession branch 3 times, most recently from d639e9c to 6f151ae Compare April 14, 2016 11:27
@czechboy0
Copy link
Member

@danieleggert Conflicts :(

//===----------------------------------------------------------------------===//
///
/// \file
/// This file contains wrappes / helpers to import libcurl into Swift.
Copy link

Choose a reason for hiding this comment

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

typo here (wrappers)

@danieleggert
Copy link
Contributor Author

I’ll make sure conflicts get resolved once libdispatch is working.

@mominul
Copy link

mominul commented Aug 2, 2016

@danieleggert Is this pull request ready to merge?

@MaxDesiatov
Copy link
Contributor

any updates on this PR?

@parkera
Copy link
Contributor

parkera commented Oct 6, 2016

@danieleggert Thanks for your work on this. I believe it's been merged as part of the later work.

@parkera parkera closed this Oct 6, 2016
@sgharms
Copy link

sgharms commented Oct 6, 2016

@parkera Do we know which release of swift will have this content merged in?

@parkera
Copy link
Contributor

parkera commented Oct 6, 2016

It's in Swift 3 actually. Give it a shot and let us know on the mailing lists if you have any problems.

@seabaylea
Copy link
Contributor

@sgharms The main content went into Swift 3, and there's been some addition bug fixes in the 3.0.1 previews. There's still some missing function - particularly things like task cancellation. Having people "kick the tires" and provide tests for anything that doesn't work would be really useful.

@sgharms
Copy link

sgharms commented Oct 26, 2016

@seabaylea

My apologies for slow reply here. I went on vacation 😎 .

Let me admit that there's a great chance I'm exposing my profound ignorance here, so I hope I'll not embarrass myself too much.

My Environment

➜  octopress git:(master) ✗ swift --version
Swift version 3.0 (swift-3.0-RELEASE)
Target: x86_64-unknown-linux-gnu
➜  octopress git:(master) ✗ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=16.04
DISTRIB_CODENAME=xenial
DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"

Code

        import Foundation
        let config = URLSessionConfiguration.default // Session Configuration
        let session = URLSession(configuration: config) // Load configuration into Session
        let url = URL(string: "http://apple.com")!

        let task = session.dataTask(with: url, completionHandler: {
            (data, response, error) in
            print("Callback ran")

        })
        task.resume()

        print("End of line")

Output

End of line

Error

I never see "Callback ran"

Conclusion

Based on the stack trace it would seem to me that using Swift to accomplish basic HTTP operations is not supported on my platform.

@sgharms
Copy link

sgharms commented Oct 26, 2016

As supplement, I asked someone with 3.0 Mac to run the same code and got the following:

screen shot 2016-10-26 at 4 30 46 pm

I suspect the (suspended) note indicates that Playgrounds isn't working with the async call?

In any case, I find the behavior in both situations surprising and didn't see warnings around this mentioned in the guide. Am I missing something?

@dtorres
Copy link

dtorres commented Oct 26, 2016

@sgharms I am assuming you are running this in the CLI in linux. well, the request doesn't get fired because the program has already exited. You need to maintain the program running until (at least) the request has had a chance to run to see the results. Look into NSRunLoop or dispatch_main(). At least one of them should be available in Linux's Swift environment

@sgharms
Copy link

sgharms commented Oct 26, 2016

Ah! OK. I had wrongly assumed that there was a default run loop that would make sure all the spawned tasks closed. Thanks.

atrick pushed a commit to atrick/swift-corelibs-foundation that referenced this pull request Jan 12, 2021
[SKSwiftPMWorkspace] Set swiftpm config file when creating Workspace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants