Lembre-se de que os HTTPClients não são apenas para APIs!

No semestre passado, estive em um curso de Desenvolvimento de Aplicativos Móveis, especificamente Android. Claro, trabalhamos um pouco com APIs, mas o instrutor só ensinou como usar HTTPClient (no Android, pelo menos), para enviar solicitações GET para um servidor, não postar. Por exemplo:

DefaultHttpClient client = new DefaultHttpClient();
HttpGet request = new HttpGet(URLToFetch);

HttpResponse rp = client.execute(request);

if(rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
{
HttpEntity result = rp.getEntity();
pageHTML
= EntityUtils.toString(result);
}

Claro, em uso com uma API, isso pode retornar o JSON / XML relevante de que você precisa, mas e se o site não tiver uma API? O que então? Eu estava desenvolvendo um aplicativo móvel de pesquisa de turmas que reunia todas as aulas da minha escola, mas em vez de recriar um banco de dados, decidi apenas enviar manualmente um formulário para a página onde o formulário estava localizado.

Você precisa entender a estrutura subjacente de um formulário antes de enviar uma solicitação POST, mas isso é feito facilmente usando apenas as Ferramentas do desenvolvedor no Google Chrome para visualizar as opções do formulário e obter seus valores e seus valores de opções. Aqui está como eu contornei esse problema (em um dispositivo móvel, pelo menos):

private HttpClient createHttpClient()
{
//Toast.makeText(context, "HTTP Client Created", Toast.LENGTH_SHORT);
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET);
HttpProtocolParams.setUseExpectContinue(params, true);

SchemeRegistry schReg = new SchemeRegistry();
schReg
.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schReg
.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg);

return new DefaultHttpClient(conMgr, params);
}

private String getPage( String deptKey ) {
String pageHTML = "NO HTML FOUND";


try {
HttpClient client = createHttpClient();
HttpPost post = new HttpPost(CLASS_PAGE);

List<NameValuePair> pparams = new ArrayList<NameValuePair>();
pparams
.add(new BasicNameValuePair("TERM", "201220"));
pparams
.add(new BasicNameValuePair("DIVS", "A"));
pparams
.add(new BasicNameValuePair("CAMPUS", "M"));
pparams
.add(new BasicNameValuePair("SUBJ", deptKey));
pparams
.add(new BasicNameValuePair("ATTR","0ANY"));
pparams
.add(new BasicNameValuePair("CREDIT", "A"));
//pparams.add(new BasicNameValuePair("SUBJ", "CSE"));
UrlEncodedFormEntity ent;
ent
= new UrlEncodedFormEntity(pparams);

post
.setEntity(ent);
HttpResponse rp = client.execute(post);
if(rp.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity result = rp.getEntity();
pageHTML
= EntityUtils.toString(result);
}

}
catch (Exception e) {
// TODO Auto-generated catch block
e
.printStackTrace();
}

return pageHTML;

}

Agora, para a explicação, createHTTPClient cria um HTTPSClient, que permite postar em um site com Secure Socket Layer (https: //), como minha escola. Depois de criá-lo, o HTTPClient navega para CLASS_PAGE (neste caso (was.nd.edu/reg/srch/ClassSearchServlet). Examinando a estrutura do formulário, esses são todos os valores necessários para enviar o formulário. Para que um HTTPPost funcione em um formulário, você deve garantir que cada opção de formulário tenha um valor válido (você pode verificar isso usando as ferramentas do desenvolvedor do Chrome, indo para a guia de rede e executando um envio simulado do formulário para ver quais são as variáveis ​​de resposta do formulário). Depois disso, basta fazer um novo UrlEncodedFormEntity, definir a entidade da postagem e executar a postagem através do cliente, e pronto!

Essa mesma lógica deve funcionar em outras linguagens, como Python e Ruby, para aqueles de vocês que podem estar presos em uma situação semelhante. Um colega meu executou a mesma coisa em PHP com grande sucesso, sem usar bibliotecas externas. Boas postagens!