How to read form body of a GCDWebServer POST request - ios

I'm struggling to believe this is so difficult but after spending a couple of hours trying to figure it out, here I am asking the hive mind for help!
My question is very similar to this one however the answers in there don't help me as I have no keys in my form. I basically want to send a text .plist file from a PC to my app. The HTML on the page is this ..
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" id="config" name="config" accept=".plist" size=40>
<input type="submit">
</form>
This gives a very simple form with a chose file button and a submit button. I have confirmed with Wireshark that the file is attached to the form and the thing is POSTed to the GCDWebServer in my app. I can also see the following confirming the body data as the file upload is processed by the web server:
[DEBUG] Connection on socket 21 preflighting request "POST /upload" with 2045 bytes body
[DEBUG] Connection on socket 21 processing request "POST /upload" with 2045 bytes body
My POST method for handling the file is this:
[_webServer addHandlerForMethod:#"POST"
path:#"/upload"
requestClass:[GCDWebServerRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
NSString *type = [(GCDWebServerRequest*)request contentType];
NSInteger length = [(GCDWebServerRequest*)request contentLength];
BOOL hasBody = [(GCDWebServerRequest*)request hasBody];
NSString *description = [(GCDWebServerURLEncodedFormRequest*)request description];
NSLog(#"\r\nType: %#\nLength: %lu\nHas Body: %#\nHeaders: %#\nConfig: %#", type, length, hasBody?#"YES":#"NO", description, #"");
return [GCDWebServerDataResponse responseWithHTML:#"TODO UPLOADED CONFIRMATION"];
}];
I can get the content type, content length, a boolean confirmation there is a body attached, all the headers and description of the boundaries etc. But I cannot for the life of me figure out how to get the actual body content. I don't wish to save it as a file I simply want it as an NSString so I can parse it and then save the settings inside my app.
A few things I have tried:
//NSData *data = [(GCDWebServerRequest*)request data];
//NSString *config = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
//NSString *config = [(GCDWebServerMultiPartFormRequest*)request files];
//NSString *config = [[(GCDWebServerURLEncodedFormRequest*)request arguments] objectForKey:#"filename"];
The NSData one looks the most likely to me but the app crashes when calling that. If anyone has any idea how I might access the body of this posted content I would be extremely grateful!
Thanks in advance!
Plasma

You'll want to use GCDWebServerMultiPartFormRequest. There's an an example here in https://github.com/swisspol/GCDWebServer/blob/master/Mac/main.m#L257.

Related

How to move and copy Contacts to the Gmail Account iOS

This is my code for getting device contacts and I want to move and copy these contacts to my Gmail Account.
CNContactStore *contactStore = [[CNContactStore alloc] init];
NSArray *keys = [[NSArray alloc]initWithObjects:CNContactJobTitleKey,CNContactNoteKey,CNContactBirthdayKey, CNContactThumbnailImageDataKey, CNContactPhoneNumbersKey,CNContactEmailAddressesKey,CNContactTypeKey, CNContactViewController.descriptorForRequiredKeys,CNContainerIdentifierKey, nil];
CNContactFetchRequest *request = [[CNContactFetchRequest alloc] initWithKeysToFetch:keys];
request.predicate = nil;
[contactStore enumerateContactsWithFetchRequest:request error:nil usingBlock:^(CNContact* __nonnull contact, BOOL* __nonnull stop){
}];
The most fundamental place you may want to check is Google Contacts API.
But for sure it's going to be time consuming and no easy. If that's not an option, you might consider to find something proper on GitHub.
Duraing a quick search I've found this library. Even if it doesn't do exactly what you need, you can get an insight how are you supposed to integrate the Google's API.
This is what you need to do if you decide to not use third-party libraries. (More details you can find here.):
1) you need to authorize;
2) after that you may send a request that creates a new contact:
POST /m8/feeds/contacts/default/full
Content-Type: application/atom+xml
GData-Version: 3.0
...
a request body:
<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>Elizabeth</gd:givenName>
<gd:familyName>Bennet</gd:familyName>
<gd:fullName>Elizabeth Bennet</gd:fullName>
</gd:name>
<atom:content type="text">Notes</atom:content>
<gd:email rel="http://schemas.google.com/g/2005#work"
primary="true"
address="liz#gmail.com" displayName="E. Bennet"/>
<gd:email rel="http://schemas.google.com/g/2005#home"
address="liz#example.org"/>
<gd:phoneNumber rel="http://schemas.google.com/g/2005#work"
primary="true">
(206)555-1212
</gd:phoneNumber>
<gd:phoneNumber rel="http://schemas.google.com/g/2005#home">
(206)555-1213
</gd:phoneNumber>
<gd:im address="liz#gmail.com"
protocol="http://schemas.google.com/g/2005#GOOGLE_TALK"
primary="true"
rel="http://schemas.google.com/g/2005#home"/>
<gd:structuredPostalAddress
rel="http://schemas.google.com/g/2005#work"
primary="true">
<gd:city>Mountain View</gd:city>
<gd:street>1600 Amphitheatre Pkwy</gd:street>
<gd:region>CA</gd:region>
<gd:postcode>94043</gd:postcode>
<gd:country>United States</gd:country>
<gd:formattedAddress>
1600 Amphitheatre Pkwy Mountain View
</gd:formattedAddress>
</gd:structuredPostalAddress>
</atom:entry>

Convenient way to print raw HTTP request in Swift or Objective-C?

Is there a convenient way to view or print a NSMutableURLRequest as a raw HTTP request -- i.e. how it gets sent over the wire? Perhaps when the request is actually made? I'm specifically not trying to extract specific components of the request and manually compose them together. FWIW I'm loading it in a webview with WKWebView.loadRequest(r).
By raw request, I mean as it is sent over the wire -- something like:
POST /target/command HTTP/1.0
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Mobile/12D508
Content-Type: application/json
Content-Length: 38914
Custom-Header: custom-value
{"param": "value"}
The reason I'm asking is because my server seems to receive an empty request body for a particular request, while it receives request bodies on others. Would be very useful if I could debug this like I debug on my server -- by printing the raw request. I understand I could use proxy tools like Charles, but I'm hoping there's a more convenient answer.
I generally just print out all outgoing requests as a copy/pasteable cURL command with a category like this, you can probably reformat it if you don't need the functionality.
#implementation NSURLRequest (cURLRepresentation)
- (NSString *)escapeQuotesInString:(NSString *)string {
NSParameterAssert(string.length);
return [string stringByReplacingOccurrencesOfString:#"\"" withString:#"\\\""];
}
- (NSString *)cURLRepresentation {
NSMutableString *curlString = [NSMutableString stringWithFormat:#"-------\ncurl -k -X %# --dump-header -", self.HTTPMethod];
for (NSString *key in self.allHTTPHeaderFields.allKeys) {
NSString *headerKey = [self escapeQuotesInString: key];
NSString *headerValue = [self escapeQuotesInString: self.allHTTPHeaderFields[key] ];
[curlString appendFormat:#" -H \"%#: %#\"", headerKey, headerValue];
}
NSString *bodyDataString = [[NSString alloc] initWithData:self.HTTPBody encoding:NSUTF8StringEncoding];
if (bodyDataString.length) {
bodyDataString = [self escapeQuotesInString: bodyDataString];
[curlString appendFormat:#" -d \"%#\"", bodyDataString];
}
[curlString appendFormat:#" \"%#\"", self.URL.absoluteString];
[curlString appendFormat:#"\n-------"];
return curlString;
}
#end
Used RequestBin (requestb.in) instead to make sure I wasn't going crazy... Turns out there's a bug in WKWebView.loadRequest(r) where r.HTTPBody will not get passed in the request body even when non-nil. Sigh.

can we pass the username in videocore library for RTMP URL?

I am making an app based on broadcasting I am using videoCore Lib for Broadcast for that I am using below code to start rtmp session
[_session startRtmpSessionWithURL:urlForStream
andStreamKey:streamID];
urlForStream is url of wowza server like rtmp://some.tv/some/username/username/randamvalue
that Randam value is don't want to override my videos every time so i am using that url and now My Problem is VCSessionState class state is not changing it is not coming to started state and I am getting the Error here is streamsessio.mm class and [NSRL(m_runLoop) run]; i don't kow where i miss please help me out
Considering from my experience of having created my own RTMP protocol library, I thought you have to separate the URL into two parts: tcUrl and stream key. In your case, the random value is likely to be a stream key.
NSString *tcUrl;
NSString *stream;
separateRtmpUrl(urlForStream, &tcUrl, &stream);
[_session startRtmpSessionWithURL:tcUrl andStreamKey:stream];
The definition of the separateRtmpUrl function can be like this.
static void separateRtmpUrl(NSString *baseUrl, NSString **tcUrl, NSString **stream)
{
NSURL *url = [NSURL URLWithString:baseUrl];
*stream = url.pathComponents.lastObject;
*tcUrl = [NSString stringWithFormat:#"%#://%#%#", url.scheme, url.host,
[NSString pathWithComponents:
[url.pathComponents subarrayWithRange:
NSMakeRange(0, url.pathComponents.count - 1)]]];
if (url.query) {
*stream = [#[*stream , url.query] componentsJoinedByString:#"?"];
*tcUrl = [#[*tcUrl , url.query] componentsJoinedByString:#"?"];
}
}

TransloadIt image upload issue when image is too small in size in ios

While uploading the image of too small size e.g when i crop the image Transloadit server always reply with this response.
{"error":"FILE_FILTER_DECLINED_FILE","message":"One of your files was declined","reason":"file_0"}
I also tried testing response by adding STEP in the ASSEMBLY with force_accept parameter considering(hoping) that it will accept any file size. But still getting the same response.
Here is the code snippet :
Transloadit *transloadit = [[Transloadit alloc]init:TRANSLOADIT_API_KEY];
AssemblyBuilder *assembly = [[AssemblyBuilder alloc]init];
[assembly setTemplateID:TRANSLOADIT_TEMPLATE_ID];
NSData *imgData = UIImageJPEGRepresentation(imageToUpload, 1.0f);
NSError* error;
//Add a file to be uploaded with autogenerated key
[assembly addFile:imgData withError:error];
if(error!=nil)
TRANSLOADIT_LOG_ERROR(self.class,error);
NSObject<IStep>* step=[[Step alloc] init];
[step setOptionKey:#"robot" object:#"/image/resize"];
[step setOptionKey:#"width" object:#(75)];
[step setOptionKey:#"height" object:#(75)];
[step setOptionKey:#"resize_strategy" object:#"pad"];
[step setOptionKey:#"background" object:#"#000000"];
[step setOptionKey:#"force_accept" object:[NSNumber numberWithBool:YES]];
//Add the step to the assembly
[assembly addStepName:#"thumb" step:step];
//Invoke assembly, and wait for the result
TransloaditResponse* response =[transloadit invokeAssembly:assembly withError:error];
if(error!=nil)
{
TRANSLOADIT_LOG_ERROR_WITH_MESSAGE(self.class,#"Error has occured while completing assembly");
}
if([response isSuccess])
{
// success code
}
else
{
// failure code
}
If someone can help me. Thanks :)
This error can only surface if you use the file/filter robot to restrict what files can be uploaded. While I don't see you using it in your code, it might very well be used inside the saved template instructions you're referencing by TRANSLOADIT_TEMPLATE_ID

Instagram comments API can't add 'text' value

My requested URL is https://api.instagram.com/v1/media/MYMEDIA_ID/comments?access_token=MYTOKEN&text=MYTEXT
I get a reply like this:
{
meta = {
code = 400;
"error_message" = "Missing 'text'";
"error_type" = APIInvalidParametersError;
};
}
In the Instagram document it says the comment API takes two parameters: text and access_token. I have provided both, and I get the error saying text is missing.
I have tried with different symbols instead of & but nothing works. Does anybody have experience on how the text parameter should appear on the requested URL?
Thanks a lot !
i am using hybridauth, and here is the code, it is working..
function setUserComment($post_id, $message)
{
$flag = 0;
$parameters = array("text" => $message);
$response = $this->api->post( "media/$post_id/comments", $parameters );
// check the last HTTP status code returned
if ( $this->api->http_code != 200 ){
throw new Exception( "Comment failed! {$this->providerId} returned an error. " . $this->errorMessageByStatus( $this->api->http_code ) );
}
else{
$flag = 1;
}
return $flag;
}
To add comments to Instagram you need to post the text it shouldn't be part of the URL. The Instagram API documentation provides an example using CURL:
curl -F 'access_token=1084932.f59def8.deb7db76ffc34f96bada217fe0b6cd9a' \
-F 'text=This+is+my+comment' \
https://api.instagram.com/v1/media/{media-id}/comments
So neither the access_token or the text are part of the URL just POST data.
Just add text=MYTEXT to your request's HTTPBody.
Here is sample code:
NSMutableURLRequest *apiRequest = [[NSMutableURLRequest alloc] initWithURL:apiURL];
apiRequest.HTTPMethod = #"POST";
NSMutableData *body = [NSMutableData data];
[body appendData:[[NSString stringWithFormat:#"text=%#", MYTEXT] dataUsingEncoding:NSUTF8StringEncoding]];
apiRequest.HTTPBody = body;
[NSURLConnection sendAsynchronousRequest:apiRequest queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
// Handle the response.
}];
you need to change the content type of the request ContentType="comment"
I believe the key here is ContentType header. At least nothing worked for me until I started to define it.
If you set "ContentType": "multipart/form-data" you need to set up quite a complex body content as described here:
https://dotnetthoughts.net/post-requests-from-azure-logic-apps/
I found much easier path:
Set your header "Content-Type": "application/x-www-form-urlencoded"
and then you can set your request body as simple as key=url_escaped(value):
text=My%20comment

Resources