Again, I do not get the error you describe. The most common reason for a 400 error from that server is missing the initial slash from the path part.
In other words, make sure the first line (ending with "\r\n") of your request is
Code:
GET /olddb?mode=html&band=all&limit=50&findcall=&findreporter=&sort=date HTTP/1.0
and not
Code:
GET olddb?mode=html&band=all&limit=50&findcall=&findreporter=&sort=date HTTP/1.0
I probably should not do this -- spoonfeeding code like this is rarely constructive --, but here is a very crude bare-bones example I used to verify this; client.c:
Code:
#define _POSIX_C_SOURCE 200809L
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#define HAD_EACCES (1<<0)
#define HAD_ETIMEDOUT (1<<1)
#define HAD_ECONNREFUSED (1<<2)
#define HAD_ENETUNREACH (1<<3)
size_t http_get(const char *const host,
const char *const port,
const char *const path,
char **const result_data,
size_t *const result_size)
{
const char *const serv = (port == NULL || port[0] == '\0') ? "http" : port;
const char *const abspath = (path == NULL || path[0] == '\0') ? "/" : path;
struct addrinfo hints, *curr, *list = NULL;
int result, descriptor;
unsigned char *data;
size_t size, used = 0;
if (!host || !result_data || !result_size) {
errno = EINVAL;
return 0;
}
if (*result_size) {
data = (unsigned char *)(*result_data);
size = *result_size;
} else {
data = NULL;
size = 0;
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
hints.ai_socktype = SOCK_STREAM; /* TCP */
result = getaddrinfo(host, serv, &hints, &list);
if (result) {
errno = ENOENT; /* No such host/port */
return 0;
}
result = 0;
descriptor = -1;
for (curr = list; curr != NULL; curr = curr->ai_next) {
descriptor = socket(curr->ai_family, curr->ai_socktype, curr->ai_protocol);
if (descriptor == -1)
continue;
if (connect(descriptor, curr->ai_addr, curr->ai_addrlen) != -1)
break;
switch (errno) {
case EACCES:
case EPERM:
result |= HAD_EACCES;
break;
case ECONNREFUSED:
result |= HAD_ECONNREFUSED;
break;
case ENETUNREACH:
result |= HAD_ENETUNREACH;
break;
case ETIMEDOUT:
result |= HAD_ETIMEDOUT;
break;
}
close(descriptor);
descriptor = -1;
}
freeaddrinfo(list);
if (descriptor == -1) {
if (result & HAD_EACCES)
errno = EACCES;
else
if (result & HAD_ETIMEDOUT)
errno = ETIMEDOUT;
else
if (result & HAD_ECONNREFUSED)
errno = ECONNREFUSED;
else
if (result & HAD_ENETUNREACH)
errno = ENETUNREACH;
else
errno = EHOSTUNREACH;
return 0;
}
while (1) {
result = snprintf((char *)data, size, "GET %s HTTP/1.0\r\nHost: %s\r\nConnection: close\r\n\r\n", abspath, host);
if (result < 0) {
close(descriptor);
errno = EINVAL;
return 0;
}
if ((size_t)result < size) {
used = (size_t)result;
break;
}
size = ((size_t)result | 2047) + 2049;
data = realloc(data, size);
if (!data) {
close(descriptor);
errno = ENOMEM;
return 0;
}
*result_data = (char *)data;
*result_size = size;
}
/* Send request. */
{
const char *p = (char *)data;
const char *const q = (char *)data + used;
ssize_t n;
while (p < q) {
n = write(descriptor, p, (size_t)(q - p));
if (n > 0)
p += n;
else
if (n != (ssize_t)-1) {
close(descriptor);
errno = EIO;
return 0;
} else
if (errno != EAGAIN && errno != EINTR) {
const int saved_errno = errno;
close(descriptor);
errno = saved_errno;
return 0;
}
}
}
used = 0;
/* Receive all. */
while (1) {
ssize_t n;
if (used >= size) {
size = (used | 2047) + 2049;
data = realloc(data, size);
if (!data) {
close(descriptor);
errno = ENOMEM;
return 0;
}
*result_data = (char *)data;
*result_size = size;
}
n = read(descriptor, data + used, size - used);
if (n > 0)
used += n;
else
if (n == 0)
break;
else
if (n != (ssize_t)-1) {
close(descriptor);
errno = EIO;
return 0;
} else
if (errno != EAGAIN && errno != EINTR) {
const int saved_errno = errno;
close(descriptor);
errno = saved_errno;
return 0;
}
}
close(descriptor);
if (used < 1) {
errno = ECONNREFUSED;
return 0;
}
if (used >= size) {
size = used + 1;
data = realloc(data, size);
if (!data) {
errno = ENOMEM;
return 0;
}
*result_data = (char *)data;
*result_size = size;
}
errno = 0;
data[used] = '\0';
return used;
}
int main(int argc, char *argv[])
{
char *response = NULL;
size_t response_maxlength = 0;
size_t response_length;
if (argc != 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s HOST PATH\n", argv[0]);
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
response_length = http_get(argv[1], NULL, argv[2], &response, &response_maxlength);
if (!response_length) {
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
fprintf(stderr, "Received a %zu-byte response:\n", response_length);
fflush(stderr);
fwrite(response, response_length, 1, stdout);
fflush(stdout);
return EXIT_SUCCESS;
}
compiling it using
gcc -Wall -Wextra -std=c99 -O2 client.c -o example
and running it using
Code:
./example www.wsprnet.org '/olddb?mode=html&band=all&limit=50&findcall=&findreporter=&sort=date'
works just fine, producing the output
Received a 29562-byte response:
to standard error, and
Code:
HTTP/1.1 200 OK
Date: Thu, 26 Nov 2015 15:52:12 GMT
Server: Apache/2.4.7 (Ubuntu)
Content-Location: olddb.php
Vary: negotiate,Accept-Encoding
TCN: choice
X-Powered-By: PHP/5.5.9-1ubuntu4.11
Connection: close
Content-Type: text/html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-15">
<meta name="MSSmartTagsPreventParsing" content="true">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Refresh" content="300">
<title>WSPR Spots</title>
<link rel="alternate" title="MEPT Spots RSS" href="http://wsprnet.org/olddb?mode=rss" type="application/rss+xml">
<style type="text/css">
#oddrow { background-color: #382836; }
#evenrow { background-color: #30202d; }
A:link { color: #ffff00; }
A:visited { color: #ffff00; }
A:active { color: #ffff00; }
</style>
</head>
to standard output (most of the output omitted for brevity).