Net/http - Confirming the right implementation

Hey folks, I am trying to use net/http and net/https to implement a specific POST call for youtube's video upload service (am trying to use the direct upload API) and am looking to confirm that I am implementing the net/http library properly to do this. The full POST call is as follows (this comes from the youtube API):

POST /feeds/api/users/default/uploads HTTP/1.1
Host: uploads.gdata.youtube.com
Authorization: ClientLogin auth=my_auth_token_here
X-GData-Key: key=my_dev_id_here
Slug: videofilename.mpg
Content-Type: multipart/related; boundary="f93dcbA3"
Content-Length: 1941255
Connection: close

--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry <http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_entry> xmlns="http://www.w3.org/2005/Atom"
  xmlns:media="http://search.yahoo.com/mrss/"
  xmlns:yt="http://gdata.youtube.com/schemas/2007">
  <media:group <http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:group>>
    <media:title <http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:title> type="plain">My Video Title Here</media:title>
    <media:description <http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:description> type="plain">
      My Video Description Here
    </media:description>
    <media:category <http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:category>
      scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People
    </media:category>
    <media:keywords <http://code.google.com/apis/youtube/reference.html#youtube_data_api_tag_media:keywords>>cat_keyword1, cat_keyword2</media:keywords>
  </media:group>
</entry>
--f93dcbA3
Content-Type: video/mp4
Content-Transfer-Encoding: binary

full_video_file_binary_contents_here
--f93dcbA3--

Here is the code I am using to implement this, am hoping to make sure that I am using net/http correctly to pass all of the data where it needs to be.

dev_id = 'my_YT_dev_id_here'
upload_host = 'uploads.gdata.youtube.com'
upload_path = '/feeds/api/users/my_username_here/uploads'

youtube_direct_upload( upload_host, upload_path, dev_id, video )

def youtube_direct_upload( host, path, dev_id, token, video )
   data = <<"DATA"
--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom"
  xmlns:media="http://search.yahoo.com/mrss/"
  xmlns:yt="http://gdata.youtube.com/schemas/2007">
  <media:group>
    <media:title type="plain">My Video Test</media:title>
    <media:description type="plain">
      Video Upload Test
    </media:description>
    <media:category
      scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People
    </media:category>
    <media:keywords>test, video</media:keywords>
  </media:group>
</entry>
--f93dcbA3
Content-Type: video/mpg
Content-Transfer-Encoding: binary

#{video}
--f93dcbA3--
DATA

   http = Net::HTTP.new( host, 443 )
   http.use_ssl = true

   headers = {
     'Host' => "#{host}",
     'Authorization' => "GoogleLogin auth=#{token}",
     'X-GData-Key' => "key=#{dev_id}",
     'Slug' => 'videofile.mpg',
     'Content-Type' => 'multipart/related; boundary="f93dcbA3"',
     'Content-Length' => data.length.to_s,
     'Connection' => 'close'
   }

   resp, data = http.post( path, data, headers )

   puts 'Code: ' + resp.code
   puts 'Data: '
   puts data

end

I left out the code which rerieves the auth_token from the youtube server as I have tested that aspect and it works fine, only having trouble getting the above to work, when I try it I get this string of errors:

/usr/local/lib/ruby/1.8/openssl/buffering.rb:178:in `syswrite': Broken pipe (Errno::EPIPE)
        from /usr/local/lib/ruby/1.8/openssl/buffering.rb:178:in `do_write'
        from /usr/local/lib/ruby/1.8/openssl/buffering.rb:192:in `write'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:175:in `write0'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:151:in `write'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:166:in `writing'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:150:in `write'
        from /usr/local/lib/ruby/1.8/net/http.rb:1514:in `send_request_with_body'
        from /usr/local/lib/ruby/1.8/net/http.rb:1496:in `exec'
        from /usr/local/lib/ruby/1.8/net/http.rb:1044:in `request'
        from /usr/local/lib/ruby/1.8/net/http.rb:1033:in `request'
        from /usr/local/lib/ruby/1.8/net/http.rb:545:in `start'
        from /usr/local/lib/ruby/1.8/net/http.rb:1031:in `request'
        from /usr/local/lib/ruby/1.8/net/http.rb:840:in `post'
        from youtube_auth.rb:95:in `youtube_direct_upload'

I am hoping that I have simply implemented the net/http library incorrectly, but am not sure... Any help would be greatly appreciated.

Thanks,
Andy

Hmm... Have you tried taking your post out of the
youtube_direct_upload method to see if you get the same error? Maybe
try these one by one to see if you can narrow it down:

Get rid of the headers
Get rid of the post body

Also, I assume that you have require 'net/http' and require 'net/
https' somewhere in there. You'd probably be getting a different
error if not.

The comments that I have around line 840 in http.rb say that the post
data must be a string. Maybe your video content is causing problems
(which would be a problem!).

-Kyle

···

On Apr 15, 8:22 pm, Andrew Cowan <iccu...@gmdstudios.com> wrote:

Hey folks, I am trying to use net/http and net/https to implement a
specific POST call for youtube's video upload service (am trying to use
the direct upload API) and am looking to confirm that I am implementing
the net/http library properly to do this. The full POST call is as
follows (this comes from the youtube API):

POST /feeds/api/users/default/uploads HTTP/1.1
Host: uploads.gdata.youtube.com
Authorization: ClientLogin auth=my_auth_token_here
X-GData-Key: key=my_dev_id_here
Slug: videofilename.mpg
Content-Type: multipart/related; boundary="f93dcbA3"
Content-Length: 1941255
Connection: close

--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry <API Reference  |  YouTube Data API  |  Google for Developers; xmlns="http://www.w3.org/2005/Atom&quot;
  xmlns:media="http://search.yahoo.com/mrss/&quot;
  xmlns:yt="http://gdata.youtube.com/schemas/2007&quot;&gt;
  <media:group <API Reference  |  YouTube Data API  |  Google for Developers;
    <media:title <API Reference  |  YouTube Data API  |  Google for Developers; type="plain">My Video Title Here</media:title>
    <media:description <API Reference  |  YouTube Data API  |  Google for Developers; type="plain">
      My Video Description Here
    </media:description>
    <media:category <API Reference  |  YouTube Data API  |  Google for Developers;
      scheme="http://gdata.youtube.com/schemas/2007/categories.cat&quot;&gt;People
    </media:category>
    <media:keywords <API Reference  |  YouTube Data API  |  Google for Developers, cat_keyword2</media:keywords>
  </media:group>
</entry>
--f93dcbA3
Content-Type: video/mp4
Content-Transfer-Encoding: binary

full_video_file_binary_contents_here
--f93dcbA3--

Here is the code I am using to implement this, am hoping to make sure
that I am using net/http correctly to pass all of the data where it
needs to be.

dev_id = 'my_YT_dev_id_here'
upload_host = 'uploads.gdata.youtube.com'
upload_path = '/feeds/api/users/my_username_here/uploads'

youtube_direct_upload( upload_host, upload_path, dev_id, video )

def youtube_direct_upload( host, path, dev_id, token, video )
   data = <<"DATA"
--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom&quot;
  xmlns:media="http://search.yahoo.com/mrss/&quot;
  xmlns:yt="http://gdata.youtube.com/schemas/2007&quot;&gt;
  <media:group>
    <media:title type="plain">My Video Test</media:title>
    <media:description type="plain">
      Video Upload Test
    </media:description>
    <media:category
      scheme="http://gdata.youtube.com/schemas/2007/categories.cat&quot;&gt;People
    </media:category>
    <media:keywords>test, video</media:keywords>
  </media:group>
</entry>
--f93dcbA3
Content-Type: video/mpg
Content-Transfer-Encoding: binary

#{video}
--f93dcbA3--
DATA

   http = Net::HTTP.new( host, 443 )
   http.use_ssl = true

   headers = {
     'Host' => "#{host}",
     'Authorization' => "GoogleLogin auth=#{token}",
     'X-GData-Key' => "key=#{dev_id}",
     'Slug' => 'videofile.mpg',
     'Content-Type' => 'multipart/related; boundary="f93dcbA3"',
     'Content-Length' => data.length.to_s,
     'Connection' => 'close'
   }

   resp, data = http.post( path, data, headers )

   puts 'Code: ' + resp.code
   puts 'Data: '
   puts data

end

I left out the code which rerieves the auth_token from the youtube
server as I have tested that aspect and it works fine, only having
trouble getting the above to work, when I try it I get this string of
errors:

/usr/local/lib/ruby/1.8/openssl/buffering.rb:178:in `syswrite': Broken
pipe (Errno::EPIPE)
        from /usr/local/lib/ruby/1.8/openssl/buffering.rb:178:in `do_write'
        from /usr/local/lib/ruby/1.8/openssl/buffering.rb:192:in `write'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:175:in `write0'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:151:in `write'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:166:in `writing'
        from /usr/local/lib/ruby/1.8/net/protocol.rb:150:in `write'
        from /usr/local/lib/ruby/1.8/net/http.rb:1514:in
`send_request_with_body'
        from /usr/local/lib/ruby/1.8/net/http.rb:1496:in `exec'
        from /usr/local/lib/ruby/1.8/net/http.rb:1044:in `request'
        from /usr/local/lib/ruby/1.8/net/http.rb:1033:in `request'
        from /usr/local/lib/ruby/1.8/net/http.rb:545:in `start'
        from /usr/local/lib/ruby/1.8/net/http.rb:1031:in `request'
        from /usr/local/lib/ruby/1.8/net/http.rb:840:in `post'
        from youtube_auth.rb:95:in `youtube_direct_upload'

I am hoping that I have simply implemented the net/http library
incorrectly, but am not sure... Any help would be greatly appreciated.

Thanks,
Andy

I wanted to post a followup to this, I finally realized that I was trying to use an ssl connection to the uploads. server for the direct upload api when that was only needed for obtaining the ClientLogin auth key. Replacing that with a normal http:// call solved the issue.

-Andy

Andrew Cowan wrote:

···

Hey folks, I am trying to use net/http and net/https to implement a specific POST call for youtube's video upload service (am trying to use the direct upload API) and am looking to confirm that I am implementing the net/http library properly to do this. The full POST call is as follows (this comes from the youtube API):

POST /feeds/api/users/default/uploads HTTP/1.1
Host: uploads.gdata.youtube.com
Authorization: ClientLogin auth=my_auth_token_here
X-GData-Key: key=my_dev_id_here
Slug: videofilename.mpg
Content-Type: multipart/related; boundary="f93dcbA3"
Content-Length: 1941255
Connection: close

--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry <API Reference  |  YouTube Data API  |  Google for Developers; xmlns="http://www.w3.org/2005/Atom&quot;
xmlns:media="http://search.yahoo.com/mrss/&quot;
xmlns:yt="http://gdata.youtube.com/schemas/2007&quot;&gt;
<media:group <API Reference  |  YouTube Data API  |  Google for Developers;

   <media:title <API Reference  |  YouTube Data API  |  Google for Developers; type="plain">My Video Title Here</media:title>
   <media:description <API Reference  |  YouTube Data API  |  Google for Developers; type="plain">
     My Video Description Here
   </media:description>
   <media:category <API Reference  |  YouTube Data API  |  Google for Developers;

     scheme="http://gdata.youtube.com/schemas/2007/categories.cat&quot;&gt;People
   </media:category>
   <media:keywords <API Reference  |  YouTube Data API  |  Google for Developers, cat_keyword2</media:keywords>
</media:group>
</entry>
--f93dcbA3
Content-Type: video/mp4
Content-Transfer-Encoding: binary

full_video_file_binary_contents_here
--f93dcbA3--

Here is the code I am using to implement this, am hoping to make sure that I am using net/http correctly to pass all of the data where it needs to be.

dev_id = 'my_YT_dev_id_here'
upload_host = 'uploads.gdata.youtube.com'
upload_path = '/feeds/api/users/my_username_here/uploads'

youtube_direct_upload( upload_host, upload_path, dev_id, video )

def youtube_direct_upload( host, path, dev_id, token, video )
  data = <<"DATA"
--f93dcbA3
Content-Type: application/atom+xml; charset=UTF-8

<?xml version="1.0"?>
<entry xmlns="http://www.w3.org/2005/Atom&quot;
xmlns:media="http://search.yahoo.com/mrss/&quot;
xmlns:yt="http://gdata.youtube.com/schemas/2007&quot;&gt;
<media:group>
   <media:title type="plain">My Video Test</media:title>
   <media:description type="plain">
     Video Upload Test
   </media:description>
   <media:category
     scheme="http://gdata.youtube.com/schemas/2007/categories.cat&quot;&gt;People
   </media:category>
   <media:keywords>test, video</media:keywords>
</media:group>
</entry>
--f93dcbA3
Content-Type: video/mpg
Content-Transfer-Encoding: binary

#{video}
--f93dcbA3--
DATA

  http = Net::HTTP.new( host, 443 )
  http.use_ssl = true

  headers = {
    'Host' => "#{host}",
    'Authorization' => "GoogleLogin auth=#{token}",
    'X-GData-Key' => "key=#{dev_id}",
    'Slug' => 'videofile.mpg',
    'Content-Type' => 'multipart/related; boundary="f93dcbA3"',
    'Content-Length' => data.length.to_s,
    'Connection' => 'close'
  }

  resp, data = http.post( path, data, headers )

  puts 'Code: ' + resp.code
  puts 'Data: '
  puts data

end

I left out the code which rerieves the auth_token from the youtube server as I have tested that aspect and it works fine, only having trouble getting the above to work, when I try it I get this string of errors:

/usr/local/lib/ruby/1.8/openssl/buffering.rb:178:in `syswrite': Broken pipe (Errno::EPIPE)
       from /usr/local/lib/ruby/1.8/openssl/buffering.rb:178:in `do_write'
       from /usr/local/lib/ruby/1.8/openssl/buffering.rb:192:in `write'
       from /usr/local/lib/ruby/1.8/net/protocol.rb:175:in `write0'
       from /usr/local/lib/ruby/1.8/net/protocol.rb:151:in `write'
       from /usr/local/lib/ruby/1.8/net/protocol.rb:166:in `writing'
       from /usr/local/lib/ruby/1.8/net/protocol.rb:150:in `write'
       from /usr/local/lib/ruby/1.8/net/http.rb:1514:in `send_request_with_body'
       from /usr/local/lib/ruby/1.8/net/http.rb:1496:in `exec'
       from /usr/local/lib/ruby/1.8/net/http.rb:1044:in `request'
       from /usr/local/lib/ruby/1.8/net/http.rb:1033:in `request'
       from /usr/local/lib/ruby/1.8/net/http.rb:545:in `start'
       from /usr/local/lib/ruby/1.8/net/http.rb:1031:in `request'
       from /usr/local/lib/ruby/1.8/net/http.rb:840:in `post'
       from youtube_auth.rb:95:in `youtube_direct_upload'

I am hoping that I have simply implemented the net/http library incorrectly, but am not sure... Any help would be greatly appreciated.

Thanks,
Andy