Trying to send non-SOAP rate request to FedEx. The following XML works with SOAP Env and Body when I send their SOAP endpoint. It says in the documentation that they offer an XML-only solution, and that is formatted exactly the same as the SOAP request. Sending to https://wsbeta.fedex.com:443/xml. Please let me know if anyone has any insight.
<RateRequest>
<WebAuthenticationDetail>
<UserCredential>
<Key>omitted</Key>
<Password>omitted</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>omitted</AccountNumber>
<MeterNumber>omitted</MeterNumber>
</ClientDetail>
<Version>
<ServiceId>crs</ServiceId>
<Major>28</Major>
<Intermediate>0</Intermediate>
<Minor>0</Minor>
</Version>
<RequestedShipment>
<ServiceType>FEDEX_2_DAY</ServiceType>
<Shipper>
<Address>
<StreetLines>4500 WEST 46TH STREET</StreetLines>
<City>CHICAGO</City>
<StateOrProvinceCode>IL</StateOrProvinceCode>
<PostalCode>60632</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Shipper>
<Recipient>
<Address>
<City>TAMPA</City>
<StateOrProvinceCode>FL</StateOrProvinceCode>
<PostalCode>33616</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Recipient>
<PackageCount>1</PackageCount>
<RequestedPackageLineItems>
<SequenceNumber>1</SequenceNumber>
<GroupPackageCount>1</GroupPackageCount>
<Weight>
<Units>LB</Units>
<Value>10</Value>
</Weight>
</RequestedPackageLineItems>
</RequestedShipment>
</RateRequest>
It looks like you're almost there. The root element of your xml document is missing the namespace http://fedex.com/ws/rate/v28.
In a SOAP message the namespace would be defined on the Envelope element. Because the data sent via the plain XML interface does not contain the wrapping Envelope and Body tags that are specific to SOAP, you have to add the namespace to the RateRequest element.
Your request should then be:
<RateRequest xmlns="http://fedex.com/ws/rate/v28">
<WebAuthenticationDetail>
<UserCredential>
<Key>omitted</Key>
<Password>omitted</Password>
</UserCredential>
</WebAuthenticationDetail>
<ClientDetail>
<AccountNumber>omitted</AccountNumber>
<MeterNumber>omitted</MeterNumber>
</ClientDetail>
<Version>
<ServiceId>crs</ServiceId>
<Major>28</Major>
<Intermediate>0</Intermediate>
<Minor>0</Minor>
</Version>
<RequestedShipment>
<ServiceType>FEDEX_2_DAY</ServiceType>
<Shipper>
<Address>
<StreetLines>4500 WEST 46TH STREET</StreetLines>
<City>CHICAGO</City>
<StateOrProvinceCode>IL</StateOrProvinceCode>
<PostalCode>60632</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Shipper>
<Recipient>
<Address>
<City>TAMPA</City>
<StateOrProvinceCode>FL</StateOrProvinceCode>
<PostalCode>33616</PostalCode>
<CountryCode>US</CountryCode>
</Address>
</Recipient>
<PackageCount>1</PackageCount>
<RequestedPackageLineItems>
<SequenceNumber>1</SequenceNumber>
<GroupPackageCount>1</GroupPackageCount>
<Weight>
<Units>LB</Units>
<Value>10</Value>
</Weight>
</RequestedPackageLineItems>
</RequestedShipment>
</RateRequest>
Also, don't forget to set the following headers in your request:
Accept: image/gif, image/jpeg, image/pjpeg, text/plain, text/html, */*
Content-Type: text/xml
Related
I am confused how the Amazon Product API works. For my example I used this ASIN (B00Y9S4V22) which is available in the german Amazon.
I requested the data from the API with the response Group "Large,OfferFull,Offers" and was confused because the only price it returns me is "1,80". On the Amazon Page itself it shows 2,37 (orderable with Prime).
As you can see in the response below it says that there are total 3 new (In the Summary in TotalNew) - which is correct. But in the Offer Listing I only have 1 of them - the cheapest. But my goal is to get the offer which is sold by Amazon it self / prime orderable / plus-product orderable. But these offers are missing completely.
When I open the "All Offers" link I get this result:
As you can see the amazon offer is listed there - but still missing in my response.
XML Response (I removed unnecessary properties)
<Items>
<Request>
<IsValid>True</IsValid>
<ItemLookupRequest>
<Condition>All</Condition>
<IdType>ASIN</IdType>
<ItemId>B00Y9S4V22</ItemId>
<ResponseGroup>Large</ResponseGroup>
<ResponseGroup>OfferFull</ResponseGroup>
<ResponseGroup>Offers</ResponseGroup>
<VariationPage>All</VariationPage>
</ItemLookupRequest>
</Request>
<Item>
<ASIN>B00Y9S4V22</ASIN>
<ParentASIN>B01HU1G8A2</ParentASIN>
<DetailPageURL>https://www.amazon.de/Westcott-00-Geodreieck-bruchsicher-transparent/dp/B00Y9S4V22?psc=1&SubscriptionId=AKIAJAD2WJOOQC6SJGWQ&tag=cheepah-21&linkCode=xm2&camp=2025&creative=165953&creativeASIN=B00Y9S4V22</DetailPageURL>
<SalesRank>832</SalesRank>
<ItemAttributes>
<ListPrice>
<Amount>237</Amount>
<CurrencyCode>EUR</CurrencyCode>
<FormattedPrice>EUR 2,37</FormattedPrice>
</ListPrice>
</ItemAttributes>
<OfferSummary>
<LowestNewPrice>
<Amount>180</Amount>
<CurrencyCode>EUR</CurrencyCode>
<FormattedPrice>EUR 1,80</FormattedPrice>
</LowestNewPrice>
<TotalNew>3</TotalNew>
<TotalUsed>0</TotalUsed>
<TotalCollectible>0</TotalCollectible>
<TotalRefurbished>0</TotalRefurbished>
</OfferSummary>
<Offers>
<TotalOffers>1</TotalOffers>
<TotalOfferPages>1</TotalOfferPages>
<MoreOffersUrl>https://www.amazon.de/gp/offer-listing/B00Y9S4V22?SubscriptionId=AKIAJAD2WJOOQC6SJGWQ&tag=cheepah-21&linkCode=xm2&camp=2025&creative=12738&creativeASIN=B00Y9S4V22</MoreOffersUrl>
<Offer>
<Merchant>
<Name>mane Büroshop</Name>
</Merchant>
<OfferAttributes>
<Condition>New</Condition>
</OfferAttributes>
<OfferListing>
<OfferListingId>47YkU0Y7wnSskg8Uv7WqMgMXIxp3CsbATIFxuhiVJN3WRBaDRBRVgDtK4OIpe%2ByOIQQubWu4jlopsbF3uBH2AeWqyOFDpEGOLh7X%2BPjKwYsRTKgA7vy12yfzZyVVIY%2F10%2BrPSNeI24F8fo9qxj%2FLCgUdrVCFhI2a</OfferListingId>
<Price>
<Amount>180</Amount>
<CurrencyCode>EUR</CurrencyCode>
<FormattedPrice>EUR 1,80</FormattedPrice>
</Price>
<AmountSaved>
<Amount>57</Amount>
<CurrencyCode>EUR</CurrencyCode>
<FormattedPrice>EUR 0,57</FormattedPrice>
</AmountSaved>
<PercentageSaved>24</PercentageSaved>
<Availability>Versandfertig in 1 - 2 Werktagen</Availability>
<AvailabilityAttributes>
<AvailabilityType>now</AvailabilityType>
<MinimumHours>24</MinimumHours>
<MaximumHours>48</MaximumHours>
</AvailabilityAttributes>
<IsEligibleForSuperSaverShipping>0</IsEligibleForSuperSaverShipping>
<IsEligibleForPrime>0</IsEligibleForPrime>
</OfferListing>
</Offer>
</Offers>
</Item>
</Items>
And here is the Request:
<Arguments>
<Argument Name="AWSAccessKeyId" Value="---"></Argument>
<Argument Name="AssociateTag" Value="---"></Argument>
<Argument Name="Condition" Value="All"></Argument>
<Argument Name="IdType" Value="ASIN"></Argument>
<Argument Name="ItemId" Value="B00Y9S4V22"></Argument>
<Argument Name="Operation" Value="ItemLookup"></Argument>
<Argument Name="ResponseGroup" Value="Large,OfferFull,Offers"></Argument>
<Argument Name="Service" Value="AWSECommerceService"></Argument>
<Argument Name="Timestamp" Value="2018-10-30T22:14:08.000Z"></Argument>
</Arguments>
I know that there is a "ListPrice" but as far as I understand Amazon this is not always the price which is Amazon is selling it.
For anyone else who is looking for a solution:
You can also provide the argument "MerchantId" and set it to "Amazon". I am still confused why not all Offers are listed but when setting the argument "MerchantId" the response will provide the Amazon Offer (but no offer else)
I am trying to POST contact data to GContact to create a new contact. I can create a new contact if I use only "gd" XML elements, but when I try and post a "gContact" element it gives me an error. I'm sure it's something simple because I am a total amateur, but I would appreciate any help.
This works
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
<atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
<gd:name>
<gd:givenName>Jack</gd:givenName>
<gd:familyName>Masters</gd:familyName>
<gd:fullName>Jack Masters</gd:fullName>
<gd:additionalName>Rascal</gd:additionalName>
<gd:namePrefix>Sir</gd:namePrefix>
<gd:nameSuffix>II</gd:nameSuffix>
</gd:name>
<atom:content type="text">These are some testing notes.</atom:content>
<gd:email rel="http://schemas.google.com/g/2005#work" address="newtestAddress#gmail.com" primary="true" />
<gd:phoneNumber rel="http://schemas.google.com/g/2005#home" primary="true">716-999-0098</gd:phoneNumber>
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">666-8765-9087</gd:phoneNumber>
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
<gd:formattedAddress>3546 Madison Street, Chicago IL, 56879</gd:formattedAddress>
<gd:street>3546 Madison Street</gd:street>
<gd:city>Chicago</gd:city>
<gd:state>IL</gd:state>
<gd:country>USA</gd:country>
</gd:structuredPostalAddress>
</atom:entry>
But this doesn't
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<atom:entry xmlns:atom="http://www.w3.org/2005/Atom" xmlns:gd="http://schemas.google.com/g/2005">
<atom:category scheme="http://schemas.google.com/g/2005#kind" term="http://schemas.google.com/contact/2008#contact" />
<gd:name>
<gd:givenName>Jack</gd:givenName>
<gd:familyName>Masters</gd:familyName>
<gd:fullName>Jack Masters</gd:fullName>
<gd:additionalName>Rascal</gd:additionalName>
<gd:namePrefix>Sir</gd:namePrefix>
<gd:nameSuffix>II</gd:nameSuffix>
</gd:name>
<atom:content type="text">These are some testing notes.</atom:content>
<gd:email rel="http://schemas.google.com/g/2005#work" address="newtestAddress#gmail.com" primary="true" />
<gd:email rel="http://schemas.google.com/g/2005#home" address="evenNewerAddress#yahoo.com" />
<gd:phoneNumber rel="http://schemas.google.com/g/2005#home" primary="true">716-999-0098</gd:phoneNumber>
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work">666-8765-9087</gd:phoneNumber>
<gd:structuredPostalAddress rel="http://schemas.google.com/g/2005#home">
<gd:formattedAddress>3546 Madison Street, Chicago IL, 56879</gd:formattedAddress>
<gd:street>3546 Madison Street</gd:street>
<gd:city>Chicago</gd:city>
<gd:state>IL</gd:state>
<gd:country>USA</gd:country>
</gd:structuredPostalAddress>
<gContact:groupMembershipInfo href="http://www.google.com/m8/feeds/groups/default/base/14b3e56788eb41b8" />
</atom:entry>
I have tried a number of different gContact elements and nothing seems to work. I get a 400 HTTP response code every time.
This is the response detail. I can't seem to figure where the error is.
Optional(<NSHTTPURLResponse: 0x600000234480> { URL: https://www.google.com/m8/feeds/contacts/default/full?alt=json } { status code: 400, headers {
"Cache-Control" = "private, max-age=0";
"Content-Encoding" = gzip;
"Content-Type" = "text/plain; charset=UTF-8";
Date = "Tue, 07 Mar 2017 16:02:17 GMT";
Expires = "Tue, 07 Mar 2017 16:02:17 GMT";
Server = GSE;
"alt-svc" = "quic=\":443\"; ma=2592000; v=\"36,35,34\"";
"x-content-type-options" = nosniff;
"x-frame-options" = SAMEORIGIN;
"x-xss-protection" = "1; mode=block"; } })
You may want to try these recommended actions for error code 400 as given in Standard Error Responses:
invalidParameter
Do not retry without fixing the problem. You need to provide a valid value for the parameter specified in the error response.
badRequest
Do not retry without fixing the problem. You need to make changes to the API query in order for it to work.
You may want to also check this related SO post for additional insights that might help you.
I figured it out. I was literally formatting every gContact element that I was trying incorrectly. I had tried 4 separate things and wrongly assumed it was something contextual I hadn't set. In reality I had formatted all four wrong in different ways. New programmer lesson learned.
How can I add tags to a blog post in IBM Connections? The API documentation says I need to update the blog post with a PUT command. If I do so according to the documentation, then I get a 500 Internal Server error as response. Same happens when trying to create a blog post with a POST command.
Question 1: what is wrong with the command?
Question 2: is there a way to only add tags without updating the content of the blog post?
sUrl = "https://my-connect-server/blogs/%BLOGID%/api/entries/%POSTID%"
sBody = "<?xml version=""1.0"" encoding=""UTF-8""?>" & _
"<entry xmlns=""http://www.w3.org/2005/Atom"">" & _
"<id>urn:lsid:ibm.com:blogs:entry-%POSTID%</id>" & _
"<title type=""text"">Test Blog Post</title>" & _
"<summary type=""html"">new summary</summary>" & _
"<content type=""html"">new content </content>" & _
"<category term=""new-tag-1""></category>" & _
"<category term=""new-tag-2""></category>" & _
"<entry>"
Call oHttp.Open("PUT", sUrl, False)
Call oHttp.setRequestHeader("Content-Type", "application/atom+xml")
Call oHttp.send(sBody)
The reason is you are not sending a full payload to the blog api. You should send back the full Blog entry with the additions/subtractions you want to make to the XML payload.
I call the api
https://<SERVER>/blogs/5133e363-7456-4525-afe6-188960888b35/api/entries/b17182a4-7807-4adf-97c7-8ac051a3f115
I had to trim off the XML header, so it's like this:
<entry xml:lang="en" dir="ltr" xmlns="http://www.w3.org/2005/Atom">
<id>urn:lsid:ibm.com:blogs:entry-b17182a4-7807-4adf-97c7-8ac051a3f115</id>
<snx:communityUuid xmlns:snx="http://www.ibm.com/xmlns/prod/sn">5133e363-7456-4525-afe6-188960888b35</snx:communityUuid>
<link href="https://<SERVER>:443/blogs/5133e363-7456-4525-afe6-188960888b35/api/entries/b17182a4-7807-4adf-97c7-8ac051a3f115" rel="edit" type="application/atom+xml">
</link>
<link href="https://<SERVER>/blogs/5133e363-7456-4525-afe6-188960888b35/entry/Test" rel="alternate" type="text/html">
</link>
<link href="https://<SERVER>:443/blogs/5133e363-7456-4525-afe6-188960888b35/feed/entrycomments/Test/atom" rel="replies" type="application/atom+xml" thr:count="0" xmlns:thr="http://purl.org/syndication/thread/1.0">
</link>
<app:collection href="https://<SERVER>:443/blogs/5133e363-7456-4525-afe6-188960888b35/api/recommend/entries/b17182a4-7807-4adf-97c7-8ac051a3f115" xmlns:app="http://www.w3.org/2007/app">
<atom:title xmlns:atom="http://www.w3.org/2005/Atom">Likes</atom:title>
<atom:category term="recommend" scheme="http://www.ibm.com/xmlns/prod/sn/collection" xmlns:atom="http://www.w3.org/2005/Atom">
</atom:category>
<app:categories fixed="yes">
</app:categories>
</app:collection>
<app:collection href="https://<SERVER>:443/blogs/5133e363-7456-4525-afe6-188960888b35/api/entrycomments/b17182a4-7807-4adf-97c7-8ac051a3f115" xmlns:app="http://www.w3.org/2007/app">
<atom:title xmlns:atom="http://www.w3.org/2005/Atom">Comment Entries</atom:title>
<app:accept>application/atom+xml;type=entry</app:accept>
<atom:category term="comments" scheme="http://www.ibm.com/xmlns/prod/sn/collection" xmlns:atom="http://www.w3.org/2005/Atom">
</atom:category>
<app:categories fixed="yes">
</app:categories>
</app:collection>
<snx:moderation status="approved" xmlns:snx="http://www.ibm.com/xmlns/prod/sn">
</snx:moderation>
<title type="text">Test</title>
<updated>2015-08-14T11:58:05.000Z</updated>
<app:edited xmlns:app="http://www.w3.org/2007/app">2015-08-14T11:58:05.000Z</app:edited>
<published>2015-08-14T11:57:44.000Z</published>
<snx:rank scheme="http://www.ibm.com/xmlns/prod/sn/recommendations" xmlns:snx="http://www.ibm.com/xmlns/prod/sn">0</snx:rank>
<snx:rank scheme="http://www.ibm.com/xmlns/prod/sn/comment" xmlns:snx="http://www.ibm.com/xmlns/prod/sn">0</snx:rank>
<snx:rank scheme="http://www.ibm.com/xmlns/prod/sn/hit" xmlns:snx="http://www.ibm.com/xmlns/prod/sn">8</snx:rank>
<author>
<name>John Doe0</name>
<snx:userid xmlns:snx="http://www.ibm.com/xmlns/prod/sn">20000395</snx:userid>
<snx:userState xmlns:snx="http://www.ibm.com/xmlns/prod/sn">active</snx:userState>
<snx:isExternal xmlns:snx="http://www.ibm.com/xmlns/prod/sn">false</snx:isExternal>
</author>
<contributor>
<name>John Doe0</name>
<snx:userid xmlns:snx="http://www.ibm.com/xmlns/prod/sn">20000395</snx:userid>
<snx:userState xmlns:snx="http://www.ibm.com/xmlns/prod/sn">active</snx:userState>
<snx:isExternal xmlns:snx="http://www.ibm.com/xmlns/prod/sn">false</snx:isExternal>
</contributor>
<category term="test">
</category>
<category term="test2">
</category>
<app:control xmlns:app="http://www.w3.org/2007/app">
<app:draft>no</app:draft>
<snx:comments enabled="yes" days="0" xmlns:snx="http://www.ibm.com/xmlns/prod/sn">
</snx:comments>
</app:control>
<summary type="html"><p dir="ltr">Test</p></summary>
<content type="html"><p dir="ltr">Test</p></content>
</entry>
I added to the category tag before
<category term="test2">
</category>
I send a put to the same api as above, with header Content-Type: application/atom+xml and Method: PUT
You should get Status Code: 200 OK
I'm writing a google apps script that is supposed to login to a website and then crawl the site and perform different actions.
The script successfully authenticates the website and completes several get methods, but when it tries to do a Post on a PostSelect drop-down box I'm getting a 500 response code.
My script follows:
function getRaceData(browser) {
var eId = "72370";
var selectNbr = "17";
var url = "http://tnetwork.trakus.com/tnet/t_Recap.aspx?EventID=" + eId;
var options = {
"method": "get",
// Set the cookies so that we appear logged-in
"headers": {
"Cookie": browser.cookie
},
"followRedirects" : false
}
var response = UrlFetchApp.fetch(url, options);
var html = response.getContentText();
var code = response.getResponseCode();
browser.html = html;
Utilities.sleep(1000);
var url = "http://tnetwork.trakus.com/tnet/t_Recap.aspx";
var payload = {"EventIDHidden" : eId, "PostSelect" : selectNbr};
var header = {"Cookie" : browser.cookie};
var options = {"method" : "post","headers" : header,"payload":payload,"followRedirects" : false};
Logger.log(UrlFetchApp.getRequest(url, options));
**var response = UrlFetchApp.fetch(url, options);** //This line causes 500 response code.
var html = response.getContentText();
var code = response.getResponseCode();
Logger.log(html);
}
Here is the error message I receive:
Request failed for http://tnetwork.trakus.com/tnet/t_Recap.aspx returned code 500. Truncated server response: <html>
<head>
<title>Runtime Error</title>
<style>
body {font-family:"Verdana";font-weight:normal;font-size: .7em;... (use muteHttpExceptions option to examine full response) (line 190, file "PostTest")
Update: Here is the Request Header that I was able to inspect by using Google Chrome Developer Tool Network selection:
POST /tnet/t_Recap.aspx HTTP/1.1
Host: tnetwork.trakus.com
Connection: keep-alive
Content-Length: 23079
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://tnetwork.trakus.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://tnetwork.trakus.com/tnet/t_Recap.aspx?EventID=72370
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: ASP.NET_SessionId=ayek3u55dsapvxe2t5kio0a3; __utma=260442568.815817400.1426544670.1426555405.1426631681.3; __utmc=260442568; __utmz=260442568.1426544670.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none); userCredentials=username=MyUserName; .ASPXAUTH=D637CD472308F766FA8D267B85D8018028FC7981748D6B3EE9DC43166998E1F7F5A9B2A676CB1FD67560B86F40A633C4DDAAE6B13BBD0B07728E00E00977F271ABD5CC74D9AD88405CB7DD04F43F5EDDEF84EAAA14E5A3A638A744B0B76EA2FFEF2434A393E5FD699416FEA1A4EF0488671D82E4; __utma=190106350.902310224.1426544678.1426631684.1426643061.5; __utmb=190106350.3.10.1426643061; __utmc=190106350; __utmz=190106350.1426544678.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)
Also here is what I get when from logging the my UrlFetchApp.getRequest(url, options) function.
{headers{Cookie=ASP.NET_SessionId=zv2o2o55tgl2ctbse52vwln1;userCredentials=username=MyUserName;.ASPXAUTH=9980822DFE22641E55F3545CAEAFA748A39AC05A69F74A67BC656078C192769BB74A0B6F000241B36A670362019F5D14DCD1A6FD9E43718B5BC8AD89E9037DBEA1CE2A012AFFFC704D35C71EB82DAC18C644F0EBA34992604ABF2680DE97098C8BE3CB0BAEADD51C65E2EB0C8851C9E151337EA4, X-Forwarded-For=71.168.117.91}, useIntranet=false, followRedirects=false, payload=PostSelect=17&EventIDHidden=72370, method=post, validateHttpsCertificates=true, contentType=application/x-www-form-urlencoded, url=http://tnetwork.trakus.com/tnet/t_Recap.aspx}
I believe my syntax is correct and I've been able to pass the cookie successfully with all of the prior get statements and for the Login Post, so I'm not sure why this Post is failing. If anyone has any thoughts or has come across something similar, I'd appreciate your input
Update: I been review the page source a bit more carefully and wanted to share the following:
That page has a very large form that appears to include hidden inputs other than the ones in my Post statement (See below). Additionally, the Select statement has an onChange="UpdatePostView().
The UpdatePostView() is fairly straight forward:
function UpdatePostView()
{
document.TChartForm.submit();
}
Additional inputs include
<form name="TChartForm" method="post" action="t_Recap.aspx" id="TChartForm">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="eBDduN+CtRzqAG6KZjuiZQhrTRokT2cqgaabq7fy3oSZaeE+O83K0QTLMCessWWC27snsJrG607bicynkgi9j1+4a++Gpz8+S5CeD9hhjzEEH8NuJUOtgPDOV5QFkqNrGVX4g+1YehwD+A5V7K5o+j5zva1cABIEhbHoxAqKrETpZgNVDjpZWTc+Hl4NaG1aTGpARvzUTgU23CvtxwYrIAH2CVuDHeqMTo0B9aOB73e4liFQtMnj/64ETSf2eGvbgmBLKaPHDxDrRCjMRLBinWRn94lLF6Cf3ZUVoQTMU4IgpQ==" />
<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="696C68DE" />
<input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="pv3ODePltFyNx0vx4zFN/4siIO4psfHIMLofolP8T27GF4kko1Ol7wQaPQ0nuAtGCoANyMCeHmV0ecBuv/CGuv4YF2jZSIQmPtNFmSpDEh/EJvyVxljXY2d+gv8=" />
<input type="hidden" name="EventIDHidden" id="EventIDHidden" value="72370" />
<input type="hidden" id="SessionUser" value="MyUserName" />
<input type="hidden" id="SessionAccessStr" value="MyUserName" />
<div id="DisplayArea"><table class="headLinks" align="center" width="97%" cellpaddiong="0" cellspacing="0"><tr><td width="50%"><div align="left"><a style="white-space:nowrap;" href="t_RaceDay.aspx?VenueID=24&Type=TBRED&Date=03/01/2015">«««More Aqueduct Races on 03/01/2015</a></div><br /><div align="left"><a href="previous.html" onClick="history.back();return false;">«««Previous Page
</a></div><p /></td><td valign="top"><div align="right"><b>
T-Net Member: myTnetMemberName </b></div></td></tr></table><table align="center" class="topThreeContainer" cellpadding="2" cellspacing="0"><tr align="center" class="topThreeTitle"><td style="white-space:nowrap">Track</td><td style="white-space:nowrap">Official Results</td><td style="white-space:nowrap">Trakus Times</td></tr><tr><td><img src="images/TrackLogos/24.gif" /></td><td valign="top"><table cellpadding="2"><tr class="topThreeHead"><td><div style="width:40px;">Win</div></td><td><div style="width:40px;">Place</div></td><td><div style="width:40px;">Show</div></td></tr><tr><td><img width="30" height="27" src="images/HorseRacingTiles/Trakus/3.gif" /></td><td><img width="30" height="27"
additional form data omitted due to space constraints....
<select runat="server" autopostback="true" style="width:250px" id="PostSelect" onChange="UpdatePostView();" name="PostSelect"><option value="0">Race Summary</option><option value="2">1/16 Mile</option><option value="3">1/8 Mile</option><option value="4">3/16 Mile</option><option value="5">1/4 Mile (POC)</option><option value="6">5/16 Mile</option><option value="7">3/8 Mile</option><option value="8">7/16 Mile</option><option value="9">1/2 Mile (POC)</option><option value="10">9/16 Mile</option><option value="11">5/8 Mile</option><option value="12">11/16 Mile</option><option value="13">3/4 Mile (POC)</option><option value="14" selected="">13/16 Mile</option><option value="15">7/8 Mile (POC)</option><option value="16">15/16 Mile</option><option value="17">1 Mile (Finish)</option></select>
additional form data omitted due to space constraints....
Race Notes: </div></td></tr><tr><td align="right" colspan="2"><div align="right" style="font-size:8px;font-weight:bold;">Updated 3/1/2015 6:29:10 PM GMT
</div></td></tr></table></div></form>
Given this new information, I have a couple additional questions:
Do I need to add the other hidden inputs to my payload or are they embedded in the Html and therefore get submitted anyway.
Does the urlfecthapp command fire the onchange event or do I have to do something special to fire that.
What is the role of the ViewState, ViewStateGenerator and EventValidation. These were present in the login form, but I did not need to include them in the payload to login successfully.
Here is my full script if anyone would like to try it and see the results for themselves.
Full Script
Thanks again.
I am wondering if anyone can share with me an example of multipart/form-data that contains:
Some form parameters
Multiple files
EDIT: I am maintaining a similar, but more in-depth answer at: https://stackoverflow.com/a/28380690/895245
To see exactly what is happening, use nc -l or an ECHO server and a user agent like a browser or cURL.
Save the form to an .html file:
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text" value="text default">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><button type="submit">Submit</button>
</form>
Create files to upload:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
Run:
nc -l localhost 8000
Open the HTML on your browser, select the files and click on submit and check the terminal.
nc prints the request received. Firefox sent:
POST / HTTP/1.1
Host: localhost:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:29.0) Gecko/20100101 Firefox/29.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Cookie: __atuvc=34%7C7; permanent=0; _gitlab_session=226ad8a0be43681acf38c2fab9497240; __profilin=p%3Dt; request_method=GET
Connection: keep-alive
Content-Type: multipart/form-data; boundary=---------------------------9051914041544843365972754266
Content-Length: 554
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="text"
text default
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------9051914041544843365972754266
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------9051914041544843365972754266--
Aternativelly, cURL should send the same POST request as your a browser form:
nc -l localhost 8000
curl -F "text=default" -F "file1=#a.html" -F "file1=#a.txt" localhost:8000
You can do multiple tests with:
while true; do printf '' | nc -l localhost 8000; done
Many thanks to #Ciro Santilli answer! I found that his choice for boundary is quite "unhappy" because all of thoose hyphens: in fact, as #Fake Name commented, when you are using your boundary inside request it comes with two more hyphens on front:
Example:
POST / HTTP/1.1
HOST: host.example.com
Cookie: some_cookies...
Connection: Keep-Alive
Content-Type: multipart/form-data; boundary=12345
--12345
Content-Disposition: form-data; name="sometext"
some text that you wrote in your html form ...
--12345
Content-Disposition: form-data; name="name_of_post_request" filename="filename.xyz"
content of filename.xyz that you upload in your form with input[type=file]
--12345
Content-Disposition: form-data; name="image" filename="picture_of_sunset.jpg"
content of picture_of_sunset.jpg ...
--12345--
I found on this w3.org page that is possible to incapsulate multipart/mixed header in a multipart/form-data, simply choosing another boundary string inside multipart/mixed and using that one to incapsulate data. At the end, you must "close" all boundary used in FILO order to close the POST request (like:
POST / HTTP/1.1
...
Content-Type: multipart/form-data; boundary=12345
--12345
Content-Disposition: form-data; name="sometext"
some text sent via post...
--12345
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=abcde
--abcde
Content-Disposition: file; file="picture.jpg"
content of jpg...
--abcde
Content-Disposition: file; file="test.py"
content of test.py file ....
--abcde--
--12345--
Take a look at the link above.
There is an example of the multipart data (Angular):
trip-upload.component.html
<form [formGroup]="form" enctype="multipart/form-data" (ngSubmit)="submitForm()">
<div class="form-group">
<label for="trip">Trip:</label>
<input formControlName="name" type="text" id="trip" name="trip" placeholder="Name of the trip">
</div>
<div class="form-group">
<label for="guide">Guide for the trip:</label>
<input formControlName="guide" type="file" id="guide" name="guide" (change)="uploadFile($event,'guide')">
</div>
<div class="form-group">
<label for="photo">Guide for the trip:</label>
<input formControlName="photo" type="image" id="photo" name="photo" (change)="uploadFile($event, 'photo')">
</div>
<div class="form-group">
<button class="btn">Upload files</button>
</div>
</form>
2.trip-upload.component.ts
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup } from "#angular/forms";
import { HttpClient } from '#angular/common/http';
#Component({
selector: 'trip-upload',
templateUrl: './trip-upload.component.html',
styleUrls: ['./trip-upload.component.css']
})
export class TripUploadComponent implements OnInit {
public form: FormGroup;
constructor(public fb: FormBuilder, private http: HttpClient) {}
ngOnInit() {
this.form = this.fb.group({
name: [''],
photo: [null],
guide: [null]
})
}
uploadFile(event, fileType: string) {
this.updateFileFormControl(event, fileType);
}
submitForm() {
let formData: any = newFormData();
Object.keys(this.form.controls).forEach(formControlName => {
formData.append(formControlName, this.form.get(formControlName).value);
});
this.http.post('http://localhost:4200/api/trip', formData).subscribe(
(response) =>console.log(response),
(error) =>console.log(error)
)
}
private updateFileFormControl(event: Event, formControlName: string) {
const file = (event.target as HTMLInputElement).files[0];
this.form.controls[formControlName].patchValue([file]);
this.form.get(formControlName).updateValueAndValidity()
}
}
Multipart response
When Browser understand which enctype you use in your form for HTTP POST requests, user-agent configure list of name/value pairs to the server. Depending on the type and amount of data being transmitted, one of the methods will be more efficient than the other: