Archive for the ‘Apple’ Category

Making HTTP Requests in C++ with WinInet and CFNetwork

First, a disclaimer: I love cURL, but there are times when you simply do not want/need to use third-party libraries. This post has nothing to do with cURL. It has everything to do with making HTTP requests with the native API’s for doing HTTP requests on Windows and OS X.

If you are here, odds are that you’ve just spent the last few hours in a futile attempt to understand either the WinInet or CFNetwork documentation. In fairness, the documentation from Microsoft and Apple is decent enough … But let’s face it, you want a quick and dirty example and there are none.

The following snippets are complete working examples. They are simple HTTP GET requests from start to finish. They DO NOT take into consideration proxy servers or HTTP auth. They DO NOT show you how to do an HTTP post. Once you get the basics though, it’s really not that far of a leap to get the rest.

If anyone would like to dive into those subject in more detail, we certainly can. Let me know, and we can talk.

Note that there’s not a lot of error handling in the code below. Just take a look at the API docs for information about what these functions return, and how to respond to errors.

Windows via WinInet:

#include <Windows.h>
#include <WinInet.h>
#include <iostream>
#include <string>

int main(int argc, char *argv[])
{
  HINTERNET hInternet = InternetOpenW(L"MyUserAgent", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0);

  if( hInternet==NULL )
  {
    std::cout << "InternetOpenW failed with error code " << GetLastError() << std::endl;
  }
  else
  {
    HINTERNET hConnect = InternetConnectW(hInternet, L"www.your_server.com", 80, NULL, NULL, INTERNET_SERVICE_HTTP, 0, NULL);

    if( hConnect==NULL )
    {
      std::cout << "InternetConnectW failed with error code " << GetLastError() << std::endl;
    }
    else
    {
      const wchar_t* parrAcceptTypes[] = { L"text/*", NULL };
      HINTERNET hRequest = HttpOpenRequestW(hConnect, L"GET", L"", NULL, NULL, parrAcceptTypes, 0, 0);

      if( hRequest==NULL )
      {
        std::cout << "HttpOpenRequestW failed with error code " << GetLastError() << std::endl;
      }
      else
      {
        BOOL bRequestSent = HttpSendRequestW(hRequest, NULL, 0, NULL, 0);

        if( !bRequestSent )
        {
          std::cout << "HttpSendRequestW failed with error code " << GetLastError() << std::endl;
        }
        else
        {
          std::string strResponse;
          const int nBuffSize = 1024;
          char buff[nBuffSize];

          BOOL bKeepReading = true;
          DWORD dwBytesRead = -1;

          while(bKeepReading && dwBytesRead!=0)
          {
            bKeepReading = InternetReadFile( hRequest, buff, nBuffSize, &dwBytesRead );
            strResponse.append(buff, dwBytesRead);
          }

          std::cout << strResponse << std::endl;
        }

        InternetCloseHandle(hRequest);
      }

      InternetCloseHandle(hConnect);
    }

    InternetCloseHandle(hInternet);
  }

  return 0;
}

OS X via CFNetwork*

#include <iostream>
#include <fstream>
#include <CoreFoundation/CoreFoundation.h>
#include <CFNetwork/CFNetwork.h>
#include <CFNetwork/CFHTTPStream.h>

int main(int argc, char *argv[])
{
  CFURLRef cfUrl = CFURLCreateWithString(kCFAllocatorDefault, CFSTR("http://www.foo.com/stuff"), NULL);
  CFHTTPMessageRef cfHttpReq = CFHTTPMessageCreateRequest(kCFAllocatorDefault, CFSTR("GET"), cfUrl, kCFHTTPVersion1_1);

  CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, cfHttpReq);
  CFReadStreamOpen(readStream);

  CFMutableDataRef cfResp = CFDataCreateMutable(kCFAllocatorDefault, 0);

  CFIndex numBytesRead;

  do
  {
    const int nBuffSize = 1024;
    UInt8 buff[nBuffSize];
    numBytesRead = CFReadStreamRead(readStream, buff, nBuffSize);

    if( numBytesRead > 0 )
    {
      CFDataAppendBytes(cfResp, buff, numBytesRead);
    }
    else if( numBytesRead < 0 )
    {
      CFStreamError error = CFReadStreamGetError(readStream);
      std::cout << error.error << std::endl;
    }
  } while( numBytesRead > 0 );

  CFReadStreamClose(readStream);

  // to write to file, uncomment code below.
  //std::ofstream oFile;
  //oFile.open("/Users/cbarnes/Desktop/file.out", std::ios::out|std::ios::binary);
  //oFile.write( (const char*)CFDataGetBytePtr(cfResp), CFDataGetLength(cfResp));

  CFRelease(cfUrl);
  CFRelease(cfHttpReq);
  CFRelease(readStream);
  CFRelease(cfResp);

  return 0;
}

* To keep things simple, this code does not use run loops, polling, or callbacks. It just blocks until the request is complete. If you’d like to see an example of such, let me know.

More Java stuff

Before you read, just keep in mind that I am a Java developer by trade.  I may be a bit biased, but I try to be somewhat objective.

As I mentioned in a previous post, Java will be absent from future versions of OS X.  It’s not surprise, and we’ve known about it for months.  Apple is handing the reigns over to Oracle so that the actual “java people” can do the Java development.

Really, this is a long time coming and it’s absolutely the best move.  The big down side is that it just won’t be there by default (like it has been since the beginning of OS X).  Mac OS X was supposed to be the operating system of choice for Java developers, but I digress.

With all that said, Java is not a totally lost cause on OS X Lion.  While it will not be installed by default, you will be prompted to download the 1.6.0 release from Apple when trying to launch any Java applications.  At present it will install 1.6.0_24, which is the latest release from Oracle.  It seems that applet support is missing though (I would love to be proved wrong).  You may recoil in horror at the thought of applets, but you’d probably be surprised how ofter you encounter them (for legitimate purposes) and never know it.

I’m beyond overjoyed that the OpenJDK project is taking over development on the OS X port, but I am a bit dismayed at the current attitude toward Java in the Apple community.  After all, they have quite a bit of experience with resurrecting obsolete/near-dead programming languages … I’m looking at you Objective-C :)

But hey, maybe I really shouldn’t care.  Nobody uses OS X in the server world; Apple killed Xserver and OS X server may be on the same path.  It’s also not going to be too long before the only people with a need for an OS X computer are iOS application developers.

And as always, I take great comfort in knowing the “cloud” (that makes everyone’s iDevice usable) lives and breathes on linux and java :)

WWDC 2010 Keynote

I need to prefix everything I am about to say with a disclaimer:  I am not an Apple hater; I just honestly don’t understand the hype.

Apple is a great hardware company; their products are truly stunning.  I use my MacBook Pro more than any of my other computers, and I’m the defacto Mac-guy at work.  I don’t personally own an iPad/iPhone/iPod (and never have), but everybody else at my house does.   I don’t dislike Apple or their products … I very much dislike a certain rabid population of their fan base.

As a software company, I think that Apple is about average.  It’s easier to engineer software that will only run on your hardware than it is to attempt to make software that will try to handle whatever you throw at it.  Apple products (hardware/software combined) work quite well together, but there’s two sides to that coin.

So, anyway, back to the topic…

Every year, just like every other geek on the planet, I get sucked into the WWDC Keynote.  This year I was a little disappointed.

iOS

We already knew about iOS 4.  We knew what it was going to offer and quite frankly, this update is not about innovation as much as it is catching up.  I don’t always buy the quote “we didn’t do it first, but we do it best”.  Things like folders and multitasking aren’t innovative (or impressive) on a smart phone … even if you “do them better”.

iPhone 4

It’s pretty slick, but it’s not a game changer.  If it were on my carrier of choice, I might be tempted to get one.  Maybe it’s not all that impressive because we’ve seen it before … no real surprises there.

FaceTime

Really, come on…  Sure, it’s cool that this is on a cell phone, but it is really the next big thing?  I don’t know about you, but I’ve been video conferencing for years.  I’m also pretty damn sure I’d rather do it with a laptop then by holding my iPhone in my hand too.  And what if my grandmom doesn’t have an iPhone?

Now, Apple, develop an open video calling/conferencing spec that we could implement on our phones, computers, TV’s, and toasters  and I’ll jump on the bandwagon.  iPhone users video conferencing with iPhone user’s isn’t overly impressive.  I don’t know, if it were truly about changing the way we communicate, it wouldn’t just be about changing the way iPhone users communicate.

Mac Products

Maybe it’s just me, but it seems that Apple is ignoring it’s laptop/desktop line lately.  To quote Steve Jobs, not everybody needs a truck … but those of us that drive trucks would like a to be thrown a bone once in a while.  Let’s not forget that (at least for now), there is no iPhone/iPad without the developers sitting behind their MacBooks (that is, until the iPad get Xcode).

It’s quite possible though, that the Mac line isn’t in need of updating.  They are not really the company’s cash cow anyway … They’re just the incubator that hatches the little baby cash cows.

Maybe next year, the current crop will be sufficiently lagging behind to deserve a bit of an update.


All-in-all, I know all that sounds hateful, but I miss the days when Apple made me actually want to buy their products.  Today, I was just left with a “so what” attitude.