I'm writing an HTTP server and client in python. When I run my scripts for client and server in terminal everything works fine. However, when I go to my browser and type "localhost:12000" in the searchbar, I get an error saying "The page isn't working. localhost didn't send any data. ERR_EMPTY_RESPONSE". What I expect to see instead, is the content of the html file contained in the response message.
This is the code for my HTTP client.
from socket import *
clientSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 18000
clientSocket.connect(("localhost",serverPort))
request = "GET www.somepage/index.html HTTP/1.0\r\nHost: www.somepage.com\r\nConnection: close\r\nUser-Agent: Chrome/86.0.4240.183\r\nAccept: text/html, application/xhtml+xml\r\nAccept-Language: it-IT, en-US\r\nAccept-Encoding: gzip, deflate\r\nAccept-Charset: ISO-8859-1, utf-8\r\n"
print(request)
clientSocket.send(request.encode())
response = (clientSocket.recv(1024)).decode()
print(response)
clientSocket.close()
This is the code for my server.
from socket import *
from datetime import date
from time import gmtime, strftime
import calendar
serverSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
serverSocket.bind(("localhost",serverPort))
serverSocket.listen(1)
current_date = calendar.day_abbr[date.today().weekday()]+", "+date.today().strftime("%d %b %Y")+strftime(" %H:%M:%S", gmtime())+ " GMT"
while True:
connection , addr = serverSocket.accept()
request = (connection.recv(1024)).decode()
request = request.split()
method = request[0]
URL = request[1]
version = request[2]
if method == "GET" and URL == "www.somepage/index.html" and version == "HTTP/1.0":
response = "HTTP/1.0 200 OK\r\nConnection: close\r\nDate: {}\r\nServer: Apache\r\nLast-Modified: Tue, 10 Nov 2020, 6:31:00 GMT\r\nContent-Length: 72 bytes\r\nContent-Type: text/html\r\n<html>\r\n<title>PAGE TITLE</title>\r\n<body>\rThis is the body\r\n</body></html>".format(current_date)
connection.send(response.encode())
connection.close()
So the server is checking if the request line is correct and then sending the HTTP response, which I do see in the terminal, but when I try in the browser I get an error instead. I've also tried checking Wireshark and I do see the HTTP messages there, so I don't understand why my browsers says no data has been sent.
Thank you all for your help.
Edit:
I couldn't post my code in the comment so I'll try here. What I'm trying to do is create an HTTP client and server than don't implement the entire HTTP protocol, but just a few request methods and a few replies. For now I was starting with the GET method and the 200 OK reply.
This is the code for my client. I have added an extra \r\n at the end of the header in the request.
from socket import *
clientSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
clientSocket.connect(("localhost",serverPort))
request = "GET /index.html HTTP/1.0 \r\nHost: www.somepage.com\r\nConnection: close\r\nUser-Agent: Chrome/86.0.4240.183\r\nAccept: text/html, application/xhtml+xml\r\nAccept-Language: it-IT, en-US\r\nAccept-Encoding: gzip, deflate\r\nAccept-Charset: ISO-8859-1, utf-8\r\n\r\n"
print(request)
clientSocket.send(request.encode())
response = (clientSocket.recv(1024)).decode()
print(response)
clientSocket.close()
This is the code for my server, with an added \r\n at the end of header as well.
from socket import *
from datetime import date
from time import gmtime, strftime
import calendar
serverSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
serverSocket.bind(("localhost",serverPort))
serverSocket.listen(1)
current_date = calendar.day_abbr[date.today().weekday()]+", "+date.today().strftime("%d %b %Y")+strftime(" %H:%M:%S", gmtime())+ " GMT"
while True:
connection , addr = serverSocket.accept()
request = (connection.recv(1024)).decode()
request = request.split()
method = request[0]
URI = request[1]
version = request[2]
host = request[4]
if method == "GET" and URI == "/index.html" and version == "HTTP/1.0" and host == "www.somepage.com":
response = "HTTP/1.0 200 OK \r\nConnection: close\r\nDate: {}\r\nServer: Apache\r\nLast-Modified: Tue, 10 Nov 2020, 6:31:00 GMT\r\nContent-Length: 83 bytes\r\nContent-Type: text/html\r\n\r\n<html>\r\n<title>PAGE TITLE</title>\r\n<body>\rThis is the body\r\n</body></html>".format(current_date)
connection.send(response.encode())
connection.close()
I've studied the standard and I'm trying to write my code according to the specifications. What I see in my browser is this error:
error
I've also noticed that if I change my server code to this:
from socket import *
from datetime import date
from time import gmtime, strftime
import calendar
serverSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
serverSocket.bind(("localhost",serverPort))
serverSocket.listen(1)
current_date = calendar.day_abbr[date.today().weekday()]+", "+date.today().strftime("%d %b %Y")+strftime(" %H:%M:%S", gmtime())+ " GMT"
while True:
connection , addr = serverSocket.accept()
request = (connection.recv(1024)).decode()
request = request.split()
method = request[0]
URI = request[1]
version = request[2]
host = request[4]
if "GET" in request:
response = "HTTP/1.0 200 OK \r\nConnection: close\r\nDate: {}\r\nServer: Apache\r\nLast-Modified: Tue, 10 Nov 2020, 6:31:00 GMT\r\nContent-Length: 83 bytes\r\nContent-Type: text/html\r\n\r\n<html>\r\n<title>PAGE TITLE</title>\r\n<body>\rThis is the body\r\n</body></html>".format(current_date)
connection.send(response.encode())
connection.close()
where basically the only difference is the way the if statement is written, then my browser will display correctly the html, that is, I see this:
page
So it seems the problem lies in the syntax I used for my python code, and not the way the standard is implemented?
Thank you again so very much for your help.
I couldn't post my code in the comment so I'll try here. What I'm trying to do is create an HTTP client and server than don't implement the entire HTTP protocol, but just a few request methods and a few replies. For now I was starting with the GET method and the 200 OK reply.
This is the code for my client. I have added an extra \r\n at the end of the header in the request.
from socket import *
clientSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
clientSocket.connect(("localhost",serverPort))
request = "GET /index.html HTTP/1.0 \r\nHost: www.somepage.com\r\nConnection: close\r\nUser-Agent: Chrome/86.0.4240.183\r\nAccept: text/html, application/xhtml+xml\r\nAccept-Language: it-IT, en-US\r\nAccept-Encoding: gzip, deflate\r\nAccept-Charset: ISO-8859-1, utf-8\r\n\r\n"
print(request)
clientSocket.send(request.encode())
response = (clientSocket.recv(1024)).decode()
print(response)
clientSocket.close()
This is the code for my server, with an added \r\n at the end of header as well.
from socket import *
from datetime import date
from time import gmtime, strftime
import calendar
serverSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
serverSocket.bind(("localhost",serverPort))
serverSocket.listen(1)
current_date = calendar.day_abbr[date.today().weekday()]+", "+date.today().strftime("%d %b %Y")+strftime(" %H:%M:%S", gmtime())+ " GMT"
while True:
connection , addr = serverSocket.accept()
request = (connection.recv(1024)).decode()
request = request.split()
method = request[0]
URI = request[1]
version = request[2]
host = request[4]
if method == "GET" and URI == "/index.html" and version == "HTTP/1.0" and host == "www.somepage.com":
response = "HTTP/1.0 200 OK \r\nConnection: close\r\nDate: {}\r\nServer: Apache\r\nLast-Modified: Tue, 10 Nov 2020, 6:31:00 GMT\r\nContent-Length: 83 bytes\r\nContent-Type: text/html\r\n\r\n<html>\r\n<title>PAGE TITLE</title>\r\n<body>\rThis is the body\r\n</body></html>".format(current_date)
connection.send(response.encode())
connection.close()
I've studied the standard and I'm trying to write my code according to the specifications. What I see in my browser is this error:
error
I've also noticed that if I change my server code to this:
from socket import *
from datetime import date
from time import gmtime, strftime
import calendar
serverSocket = socket(AF_INET,SOCK_STREAM)
serverPort = 12000
serverSocket.bind(("localhost",serverPort))
serverSocket.listen(1)
current_date = calendar.day_abbr[date.today().weekday()]+", "+date.today().strftime("%d %b %Y")+strftime(" %H:%M:%S", gmtime())+ " GMT"
while True:
connection , addr = serverSocket.accept()
request = (connection.recv(1024)).decode()
request = request.split()
method = request[0]
URI = request[1]
version = request[2]
host = request[4]
if "GET" in request:
response = "HTTP/1.0 200 OK \r\nConnection: close\r\nDate: {}\r\nServer: Apache\r\nLast-Modified: Tue, 10 Nov 2020, 6:31:00 GMT\r\nContent-Length: 83 bytes\r\nContent-Type: text/html\r\n\r\n<html>\r\n<title>PAGE TITLE</title>\r\n<body>\rThis is the body\r\n</body></html>".format(current_date)
connection.send(response.encode())
connection.close()
where basically the only difference is the way the if statement is written, then my browser will display correctly the html, that is, I see this:
page
So it seems the problem lies in the syntax I used for my python code, and not the way the standard is implemented?
Thank you again so very much for your help.
request = "GET www.somepage/index.html HTTP/1.0\r\nHost: www.somepage.com\r\nConnection: close\r\nUser-Agent: Chrome/86.0.4240.183\r\nAccept: text/html, application/xhtml+xml\r\nAccept-Language: it-IT, en-US\r\nAccept-Encoding: gzip, deflate\r\nAccept-Charset: ISO-8859-1, utf-8\r\n"
This is not a valid HTTP request. First, it should only contain the path /index.html and not domain/path as you currently do. It is also missing the final \r\n at the end which signals the end of the HTTP header.
In the same way the expectations of the server wrong too, which explains why it causes problems when faced with a client correctly implementing HTTP (the browser). Additionally the HTTP response is also missing the final \r\n after the HTTP header and the Content-length: 72 does not match the actual length of the content.
Please don't implement HTTP by (wrongly) second-guessing how it works. There is an actual standard for this and implementations are expected to follow this standard.
After the edit the code looks like this:
request = request.split()
...
version = request[2]
host = request[4]
if method == "GET" and URI == "/index.html" and version == "HTTP/1.0" and host == "www.somepage.com":
... send response ...
There are multiple problems here: the first one is that the browser will not use HTTP/1.0 as version but HTTP/1.1.
The next problem is that the domain might not be in the variable host since it is might not be in request[4]. It is blindly assumed that the Host header is in the second line of the request since it is implemented like this in the client. But the HTTP standard does in now way require this. And while it might be the case with some clients it is not the case with others. Instead of blindly assuming that something is in a specific place in the HTTP header the header should actually be parsed properly to extract the Host header.
Related
I'm trying to setup a server using Python socket programming, using the code below:
from socket import *
serverPort = 80
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("", serverPort))
serverSocket.listen(1)
print ("The server is ready to receive")
while True:
connectionSocket, addr = serverSocket.accept()
sentence = connectionSocket.recv(1024).decode()
capitalizedSentence = sentence.upper()
connectionSocket.send(capitalizedSentence.encode())
connectionSocket.close()
When I use this code and try to enter localhost in a web browser, I get the response without any problem as shown.
But, when I change line 3 in the code to serverPort = 12000 and try to enter localhost:12000, I don't get a response.
Note: I use Windows not Linux, and I run the Python code on PyCharm 2020.3.3.
Neither example should be working, regardless of the port used, because the server is not sending back a valid HTTP response, like the error message says. The fact that the 1st example "works" is a fluke.
Try this instead:
from socket import *
serverPort = 80
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(("", serverPort))
serverSocket.listen(1)
print ("The server is ready to receive")
while True:
connectionSocket, addr = serverSocket.accept()
sentence = connectionSocket.recv(1024).decode()
capitalizedSentence = sentence.upper()
reply = "HTTP/1.0 200 OK\r\nConnection: close\r\n\r\n"
connectionSocket.send(reply.encode()) # <-- add this!
connectionSocket.send(capitalizedSentence.encode())
connectionSocket.close()
I'm trying to use Elixir to access Azure Storage Services via their REST API but I'm having difficulty getting the Authentication Header to work. I am able to connect if I use the ex_azure package (wrapper for erlazure) but not when I try to build the request and use HTTPoison.
Most Recent Error Messages
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Error>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:00000000-0000-0000-0000-000000000000\nTime:2017-08-02T21:46:08.6488342Z</Message>
<AuthenticationErrorDetail>The MAC signature found in the HTTP request '<signature>' is not the same as any computed signature. Server used following string to sign: 'GET\n\n\nWed, 02 Aug 2017 21:46:08
GMT\nx-ms-date-h:Wed, 02 Aug 2017 21:46:08 GMT\nx-ms-version-h:2017-05-10\n/storage_name/container_name?comp=list'.</AuthenticationErrorDetail>
</Error>
After 1st Edit
<?xml version=\"1.0\" encoding=\"utf-8\"?>
<Error>
<Code>AuthenticationFailed</Code>
<Message>Server failed to authenticate the request. Make sure the value of Authorization header is formed correctly including the signature.\nRequestId:00000000-0000-0000-0000-000000000000\nTime:2017-08-03T03:03:57.1385277Z</Message>
<AuthenticationErrorDetail>The MAC signature found in the HTTP request '<signature>' is not the same as any computed signature. Server used following string to sign: 'GET\n\n\n\n\n\n\n\n\n\n\n\nx-ms-date:Thu, 03 Aug
2017 03:03:57 GMT\nx-ms-version:2017-04-17\n/storage_name/container_name\ncomp:list\nrestype:container'.</AuthenticationErrorDetail>
</Error>
Dependencies
# mix.exs
defp deps do
{:httpoison, "~> 0.12"}
{:timex, "~> 3.1"}
end
Code
Am I formatting the Authentication Header (string_to_sign) right?
Am I using encode/decode right?
Am I adding headers correctly to HTTPoison?
Should I be using something else for REST actions instead of HTTPoison?
# account credentials
storage_name = "storage_name"
container_name = "container_name"
storage_key = "storage_key"
storage_service_version = "2017-04-17" # fixed version
request_date =
Timex.now
|> Timex.format!("{RFC1123}") # Wed, 02 Aug 2017 00:52:10 +0000
|> String.replace("+0000", "GMT") # Wed, 02 Aug 2017 00:52:10 GMT
# set canonicalized headers
x_ms_date = "x-ms-date:#{request_date}"
x_ms_version = "x-ms-version:#{storage_service_version}"
# assign values for string_to_sign
verb = "GET\n"
content_encoding = "\n"
content_language = "\n"
content_length = "\n"
content_md5 = "\n"
content_type = "\n"
date = "\n"
if_modified_since = "\n"
if_match = "\n"
if_none_match = "\n"
if_unmodified_since = "\n"
range = "\n"
canonicalized_headers = "#{x_ms_date}\n#{x_ms_version}\n"
canonicalized_resource = "/#{storage_name}/#{container_name}\ncomp:list\nrestype:container" # removed timeout. removed space
# concat string_to_sign
string_to_sign =
verb <>
content_encoding <>
content_language <>
content_length <>
content_md5 <>
content_type <>
date <>
if_modified_since <>
if_match <>
if_none_match <>
if_unmodified_since <>
range <>
canonicalized_headers <>
canonicalized_resource
# decode storage_key
{:ok, decoded_key} =
storage_key
|> Base.decode64
# sign and encode string_to_sign
signature =
:crypto.hmac(:sha256, decoded_key, string_to_sign)
|> Base.encode64
# build authorization header
authorization_header = "SharedKey #{storage_name}:#{signature}"
# build request and use HTTPoison
url = "https://storage_name.blob.core.windows.net/container_name?restype=container&comp=list"
headers = [ # "Date": request_date,
"x-ms-date": request_date, # fixed typo
"x-ms-version": storage_service_version, # fixed typo
# "Accept": "application/json",
"Authorization": authorization_header]
options = [ssl: [{:versions, [:'tlsv1.2']}], recv_timeout: 500]
HTTPoison.get(url, headers, options)
Notes
Some sources I used/tried...
Authentication for the Azure Storage Services
The MAC signature found in the HTTP request is not the same as any computed signature azure integration using php
How to access rest azure blob using cURL
Accessing Azure blob storage using bash, curl
A few issues I noticed:
You included Date request header in your request but it is not included in your string_to_sign. Either include this header in your string_to_sign or remove this header from request headers.
You included timeout:30 in your canonicalized_resource but it is not included in your request URL. Again, either add timeout=30 in your request querystring or remove timeout:30 from canonicalized_resource.
I have not used Elixir as such so I don't know how request headers work there, but you're naming your request headers as x-ms-date-h and x-ms-version-h. Shouldn't they be x-ms-date and x-ms-version respectively?
I have a few REST endpoints and few [asmx/svc] endpoints.
Some of them are GET and the others are POST operations.
I am trying to put together a quick and dirty , repeatable healthcheck sequence for finding if all the endpoints are responsive or if any are down.
Essentially either get a 200 or 201 and report error if otherwise.
What is the easiest way to do this?
SOAPUI use internally apache http-client 4.1.1 version, you can use it inside a groovy script testStep to perform your checks.
Add a groovy script testStep to your testCase an inside use the follow code; which basically try to perform a GET against a list of URLs, if its returns http-status 200 or 201 its considered that is working, if http-status 405 (Method not allowed) is returned then it tries with POST and perform the same status code check, otherwise it's considered down.
Note that some services can be running however can return for example 400 (BAD request) if the request is not correct, so think about if you need to rethink the way you want perform a check or add some other status codes to consider if the server is running correctly.
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.methods.HttpPost
import org.apache.http.impl.client.DefaultHttpClient
// urls to check
def urls = ['http://google.es','http://stackoverflow.com']
// apache http-client to use in closue
DefaultHttpClient httpclient = new DefaultHttpClient()
// util function to get the response
def getStatus = { httpMethod ->
HttpResponse response = httpclient.execute(httpMethod)
// consume the entity to avoid error with http-client
if(response.getEntity() != null) {
response.getEntity().consumeContent();
}
return response.getStatusLine().getStatusCode()
}
HttpGet httpget;
HttpPost httppost;
// finAll urls that are working
def urlsWorking = urls.findAll { url ->
log.info "try GET for $url"
httpget = new HttpGet(url)
def status = getStatus(httpget)
// if status are 200 or 201 it's correct
if(status in [200,201]){
log.info "$url is OK"
return true
// if GET is not allowed try with POST
}else if(status == 405){
log.info "try POST for $url"
httppost = new HttpPost(url)
status = getStatus(httpget)
// if status are 200 or 201 it's correct
if(status in [200,201]){
log.info "$url is OK"
return true
}
log.info "$url is NOT working status code: $status"
return false
}else{
log.info "$url is NOT working status code: $status"
return false
}
}
// close connection to release resources
httpclient.getConnectionManager().shutdown()
log.info "URLS WORKING:" + urlsWorking
This scripts logs:
Tue Nov 03 22:37:59 CET 2015:INFO:try GET for http://google.es
Tue Nov 03 22:38:00 CET 2015:INFO:http://google.es is OK
Tue Nov 03 22:38:00 CET 2015:INFO:try GET for http://stackoverflow.com
Tue Nov 03 22:38:03 CET 2015:INFO:http://stackoverflow.com is OK
Tue Nov 03 22:38:03 CET 2015:INFO:URLS WORKING:[http://google.es, http://stackoverflow.com]
Hope it helps,
I have written a socket program in C. I used this program as a chat server/client using TCP. I tried to change the chat server to use it as a HTTP server by changing the port to 80. I referred to the HTTP request/response format in http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Example_session , and made my program to reply with sample response. I tried the url
http://127.0.0.1/
in browser. My program read the request and replied with response. At first, I used google-chrome. Chrome didn't load the page correctly until i added the correct data length in Content-Length header. After setting content length header, chrome loaded the page correctly. But, firefox doesn't load the page. Firefox doesn't showed any errors, but still loading the page like it is still waiting for some data. Only When i stop the server or close the socket, complete page is loaded. I tried to follow rfc2616 https://www.rfc-editor.org/rfc/rfc2616 , and made the response exactly , but the still the results are same.
Request:
GET / HTTP/1.1\r\nHost: 127.0.0.1:8080\r\nUser-Agent: Mozilla/5.0
(X11; Ubuntu; Linux x86_64; rv:33.0) Gecko/20100101
Firefox/33.0\r\nAccept:
text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8\r\nAccept-Language:
en-US,en;q=0.5\r\nAccept-Encoding: gzip, deflate\r\nConnection:
keep-alive\r\n\r\n
For the above request, my program write to the socket with following response & content.
Response:
HTTP/1.1 200 OK\r\nCache-Control : no-cache, private\r\nContent-Length
: 107\r\nDate : Mon, 24 Nov 2014 10:21:21 GMT\r\n\r\n
Content:
<html><head><title></title></head><body>TIME : 1416824843 <br>DATE: Mon Nov 24 15:57:23 2014 </body></html>
This response is loading in Chrome, but not in firefox. Chrome is loading the page instantly whereas firefox is waiting for data. Note that the data length 107 is specified in the header. I donot have any addons enabled in firefox. My firefox version is in the request. Chrome version: Version 38.0.2125.111 (64-bit).
Code:
void *socket_read(void *args)
{
int socket,*s,length;
char buf[1024];
s=(int *)args;
socket=*s;
while(1){
buf[0]='\0';
length=read(socket,buf,1024);
if(length==0)
break;
else if(length==-1){
perror("Read");
return;
}
else{
printf("Request: %s\n",buf);
send_response(socket);
}
}
printf("End of read thread [%d]\n",socket);
}
int start_accept(int port)
{
int socket,csocket;
pthread_t thread;
struct sockaddr_in client;
socklen_t addrlen=sizeof(client);
pthread_attr_t attr;
socket=create_socket(port);
while(1){
if((csocket=accept(socket,(struct sockaddr *)&client,&addrlen))==-1)
{
perror("Accept");
break;
}
pthread_attr_init(&attr);
if(0!=pthread_create(&thread,&attr,socket_read,&csocket))
{
perror("Read thread");
return;
}
usleep(10000);
}
}
void send_response(int socket)
{
char buf1[1024];
int content_length;
char buf2[1024]="<html><head><title></title></head><body>TIME : 1416824843 <br>DATE: Mon Nov 24 15:57:23 2014 </body></html>";
content_length=strlen(buf2);
sprintf(buf1,"HTTP/1.1 200 OK\r\nCache-Control : no-cache, private\r\nContent-Length : %d\r\nDate : Mon, 24 Nov 2014 12:03:43 GMT\r\n\r\n",content_length);
printf("Written: %d \n",write(socket,buf1,strlen(buf1)));
fflush(stdout);
printf("Written: %d \n",write(socket,buf2,content_length));
fflush(stdout);
}
I have found the problem.
The Response is incorrect. There should not be any spaces between the header field name and colon(':'). Found this in http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2 .
My correct response is
HTTP/1.1 200 OK\r\nCache-Control: no-cache, private\r\nContent-Length: 107\r\nDate: Mon, 24 Nov 2014 10:21:21 GMT\r\n\r\n
I had put a space between 'Content-Length' and ':' . That's the reason Firefox ignored the content length header and reading the socket. Chrome accepted the header fields with spaces, so the problem didn't occurred in chrome.
After removing the space, program works fine.
It actually loads the page. If you add content-type header you will see the HTML page (Content-Type: text/html; charset=UTF-8\r\n)
Anyway, both in Chrome and in Firefox you will see the connections never stops because the server doesn't close the socket. If you closed csocket, you would see the HTML page in both browsers but as you said it should be a persistent connection.
I'm trying to connect my asp.net REST api to salesforce. I'm succesfully going through authentification, but when I start to send POST requests, I'm getting an error
{"errorCode":"INVALID_SESSION_ID","message":"Session expired or invalid"}
Here is my POST request:
//SFServerUrl = "https://na17.salesforce.com/services/";
//url = "data/v28.0/sobjects/Account";
ASCIIEncoding ascii = new ASCIIEncoding();
byte[] postBytes = ascii.GetBytes(postBody);
HttpWebRequest request = WebRequest.Create(Globals.SFServerUrl + url) as HttpWebRequest;
request.Method = "POST";
request.ContentType = "application/json";
request.ContentLength = postBytes.Length;
Stream postStream = request.GetRequestStream();
postStream.Write(postBytes, 0, postBytes.Length);
HttpCookie cookie = HttpContext.Current.Request.Cookies[Globals.SFCookie];
var ticket = FormsAuthentication.Decrypt(cookie.Value);
string authToken = ticket.UserData;
request.Headers.Add("Authorization", "Bearer " + authToken);
postStream.Close();
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
StringBuilder sb = new StringBuilder();
byte[] buf = new byte[8192];
Stream resStream = response.GetResponseStream();
string tempString = null;
int count = 0;
do
{
count = resStream.Read(buf, 0, buf.Length);
if (count != 0)
{
tempString = Encoding.ASCII.GetString(buf, 0, count);
sb.Append(tempString);
}
}
while (count > 0);
return new Tuple<bool, string>(true, sb.ToString());
When I'm trying to send GET request - I recieve 200 response.
Also, I've tried to send a POST Request with the same token from Simple Rest Client and it get's 200 response. I tried to change my "Authorization : Bearer" Header to "Authorization : Oauth", but nothing changed. I also tried to catch this error, get refresh token and send a request again with refreshed token, but nothing changed. Please, help me with this.
Using workbench I was able to POST the following JSON to /services/data/v29.0/sobjects/Account and create a new Account.
{
"Name" : "Express Logistics and Transport"
}
Raw Response
HTTP/1.1 201 Created
Date: Sun, 07 Sep 2014 21:32:06 GMT
Set-Cookie: BrowserId=_HC-bzpTQABC1237vFu2hA;Path=/;Domain=.salesforce.com;Expires=Thu, 06-Nov-2014 21:32:06 GMT
Expires: Thu, 01 Jan 1970 00:00:00 GMT
Sforce-Limit-Info: api-usage=209/15000
Location: /services/data/v29.0/sobjects/Account/0010000000000001AAA
Content-Type: application/json;charset=UTF-8
Content-Encoding: gzip
Transfer-Encoding: chunked
{
"id" : "0010000000000001AAA",
"success" : true,
"errors" : [ ]
}
Things to check:
Your URL. It appears to be missing the leading /services
Is SFServerUrl the same Salesforce pod/server that the Session Id was issued to? If the Session Id came from another pod then it would be invalid on na17.
How did you create the Session Id? If you used OAuth, what scopes did you request?
Is the Session Id coming out of the cookie valid?
Has something else using the same Session Id called logout and invalidated the session?
Incidentally, the Salesforce StackExchange site is a great place to ask Salesforce specific questions.
See also:
Using REST API Resources - Create a Record
The problem was that I added Headers after Content. When I switched these lines of code everything worked.