• Revista PROGRAMAR: Já está disponível a edição #53 da revista programar. Faz já o download aqui!

skin

fopen não funciona bem...

24 mensagens neste tópico

Eu tenho este código para validar o se um URL é válido ou não, e até agora tinha funcionado com todos os sites... mas hoje testei não sei bem porquê com o http://www.youtube.com e retornou falso em vez de verdadeiro. Alguém me sabe indicar porquê?

function url($url) {
$estado = @fopen($url,"r");
if($estado) return true;
else return false;
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bom ... se tirares o @ da função, talvez o PHP te diga porque não abriu o site :confused:

Se ele te disser que foi "Bad Request" experimenta o curl

http://php.net/curl

Ohhhhhhhhhhhhh PS

Já agora actualiza o teu código para fechar o 'resource'

$estado = @fopen();
@fclose($estado);
if () ...

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Warning: fopen(http://www.youtube.com) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request

Sim deu bad request. O curl não queria muito visto que é necessário ter a libcurl no servidor e alguns servidores não têm e este trabalho pode ir para onde não haja e dá problemas... Talvez vá fazer é uma verificação diferente.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O fopen está a funcionar sem problemas, o servidor é que está a devolver um erro 400 ao teu pedido.

Deves ter um erro qq no teu url. Algum caracter não permitido ou algum parametro que não pode ter o valor que lhe estás a atribuir.

EDIT: pois, possivelmente isso, a falta da inclusão da path no url.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Deve de ser dos headers, o google é muito meticuloso nisso (o user-agent priniciplamente).

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Experimenta o url com uma barra no fim (http://www.youtube.com/).

Warning: fopen(http://www.youtube.com/) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 400 Bad Request

The same...

Acho que vou matchar isto com regex, isto é para bem de quem utilizar por isso não têm grande vantagem em introduzir dados que não sejam válidos... :confused:

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

É esquisito que devolve um 400. Aqui, usando o curl devolve um 303, e redireciona para o mesmo sítio mas com 3 cookies.

~$ curl -I http://youtube.com/
HTTP/1.1 303 See Other
Date: Sun, 19 Oct 2008 04:07:42 GMT
Server: Apache
Set-Cookie: use_hitbox=72c46ff6cbcdb7c5585c36411b6b334edAEAAAAw; path=/; domain=.youtube.com
Set-Cookie: PREF=gl=US&hl=en; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 04:07:42 GMT
Set-Cookie: GEO=4b349fedee573c4238c75ffd85d18460cwwAAAAyU0VV4IKeAI6y+kg=; path=/; domain=.youtube.com; expires=Tue, 21-Oct-2008 04:07:42 GMT
Expires: Tue, 27 Apr 1971 19:44:06 EST
Cache-Control: no-cache
Location: http://www.youtube.com/
Content-Type: text/html; charset=utf-8

Experimenta com o curl... escreve umas funções que sirvam de alternativa para o file() e para o file_get_contents() e a partir daí fazes tudo na mesma.

Mais ou menos como está aqui:

http://wiki.dreamhost.com/CURL

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Não posso usar o curl porque isto vai ser para distribuir ou seja quantos menos requisitos externos melhor..

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Há mais serviços de alojamento com suporte para curl do que com allow_remote_fopen ou lá como se chama a directiva.

Dito isto e tendo em conta a compatibilidade, o ideial era suportares os dois silenciosamente: se um não desse automaticamen seria usado o outro método.

Estive aqui a experimentar e não há volta a dar-lhe, o youtube envia sempre um 400. Não estive a fazer testes extensos, mas tudo me leva a crer que só aceitam pedidos por parte ce clientes com suporte para cookies. Experimenta desactivar os cookies do teu browser e ve o resultado.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Acho que vou verificar se o URL introduzido é a válido a nível da sua consituição usando regex e ponho o teste do fopen e do curl para dizer se foi verificado o seu estado online.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Para detectares se tens o curl disponível em determinado sítio podes usar a função "function_exists"

if (function_exists('curl_init')) {
  /* usa curl */
} else {
  /* usa fopen */
}

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

pedrotuga, deu-te 303 porque estás a pedir youtube.com e não www.youtube.com

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

:)

pois foi, nem reparei:

 curl -I http://www.youtube.com
HTTP/1.1 200 OK
Date: Sun, 19 Oct 2008 12:06:42 GMT
Server: Apache
Set-Cookie: use_hitbox=72c46ff6cbcdb7c5585c36411b6b334edAEAAAAw; path=/; domain=.youtube.com
Set-Cookie: VISITOR_INFO1_LIVE=-QRGL0-D8VM; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 12:06:42 GMT
Set-Cookie: PREF=gl=US&hl=en; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 12:06:42 GMT
Set-Cookie: GEO=28e3d256efef72ae10fecd84dfe70e52cwwAAAAyU0VV4IKeANIi+0g=; path=/; domain=.youtube.com; expires=Tue, 21-Oct-2008 12:06:42 GMT
Expires: Tue, 27 Apr 1971 19:44:06 EST
Cache-Control: no-cache
Content-Length: 96824
Content-Type: text/html; charset=utf-8

Isso torna a situação mais esquisita ainda :)

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Mais vale usarem o wireshark para apanharem o request que estão a enviar para se poder analisar.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Bem vou ter de fazer o requeste usando sockets, já mostro o resultado.

Edit:

>>> import socket
>>> s = socket.socket()
>>> s.connect(("www.youtube.com", 80))
>>> s.send("""GET / HTTP/1.1\r\nHost:www.youtube.com\r\n\r\n""")
40
>>> s.recv(10000)
'HTTP/1.1 400 Bad Request\r\nDate: Sun, 19 Oct 2008 15:29:52 GMT\r\nServer: Apache\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nnnCoection: close\r\nTransfer-Encoding: chunked\r\nContent-Type: text/plain\r\n\r\n0\r\n\r\n'
>>> s.close()

>>> s = socket.socket()
>>> s.connect(("www.youtube.com", 80))
>>> s.send("""GET / HTTP/1.1\r\nHost:www.youtube.com\r\nUser-Agent: MeuBrowser\r\n\r\n""")
>>> s.recv(10000)
'HTTP/1.1 200 OK\r\nDate: Sun, 19 Oct 2008 15:32:49 GMT\r\nServer: Apache\r\nSet-Cookie: use_hitbox=72c46ff6cbcdb7c5585c36411b6b334edAEAAAAw; path=/; domain=.youtube.com\r\nSet-Cookie: VISITOR_INFO1_LIVE=pYypP9gcZ_g; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 15:32:49 GMT\r\nSet-Cookie: PREF=gl=US&hl=en; path=/; domain=.youtube.com; expires=Wed, 17-Oct-2018 15:32:49 GMT\r\nSet-Cookie: GEO=ba10db1306c1a0257531a9b666beff38cwwAAAAyUFRV8KYTACFT+0g=; path=/; domain=.youtube.com; expires=Tue, 21-Oct-2008 15:32:49 GMT\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nContent-Length: 96250\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/1999/REC-html401-19991224/loose.dtd">\n\n\n\t<html lang="en">\n\n
(....)

Resumindo o problema é mesmo do User-Agent.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O teu pedido deu bad-request, fnds, porque segundo a especificação 1.1 do protocolo tens de dizer o estado que é para ficar a ligação, salvo erro. Experimenta usar "GET / HTTP/1.0\r\nHost: www.youtube.com\r\n\r\n" e "GET / HTTP/1.1\r\nHost: www.youtube.com\r\nConnection: close\r\n\r\n"

Isto segundo o protocolo, porque sim, é possível que o YouTube te devolva um 400 por alternativa do programador.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

400 Bad Request

The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications. 

fonte: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Ou seja... um erro com código 400 é par aquele tipo de pedido que o dono do site não quer responder nem explicar porquê. Mas claro, para quem mantem o servidor é tecnicamente possivel enviar o que quer que seja numa qualquer dada situação.

Mas está visto, como acabou de provar o fnds, o youtube só responde com a página a quem especificar o user-agent.

Descoberto que está o problema, (skin, vas ter mesmo que usar o curl) aproveito para perguntar uma coisa:

Alguem conhece uma forma simples de enviar headers assim como o fnds fez mas sem ter que escrever um script?

Em tempos li uma forma que envolvia o uso de telnet mas já não me lembro. A libcurl é fie e permite ver os headers da resposta facilmente e mudar os headers do pedido mais ou menos facilmente... mas fixe fixe era escrever mesmo o pedido manualmente, sem  complicações.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

O teu pedido deu bad-request, fnds, porque segundo a especificação 1.1 do protocolo tens de dizer o estado que é para ficar a ligação, salvo erro. Experimenta usar "GET / HTTP/1.0\r\nHost: www.youtube.com\r\n\r\n" e "GET / HTTP/1.1\r\nHost: www.youtube.com\r\nConnection: close\r\n\r\n"

Isto segundo o protocolo, porque sim, é possível que o YouTube te devolva um 400 por alternativa do programador.

É a mesma coisa.

>>> s = socket.socket()
>>> s.connect(("www.youtube.com",80))
>>> s.send("GET / HTTP/1.0\r\nHost: www.youtube.com\r\n\r\n")
>>> s.recv(1000)
'HTTP/1.1 400 Bad Request\r\nDate: Sun, 19 Oct 2008 18:11:36 GMT\r\nServer: Apache\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nConnection: close\r\nContent-Type: text/plain\r\n\r\n'

>>> s = socket.socket()
>>> s.connect(("www.youtube.com",80))
>>> s.send("GET / HTTP/1.1\r\nHost: www.youtube.com\r\nConnection: close\r\n\r\n")
>>> s.recv(1000)
'HTTP/1.1 400 Bad Request\r\nDate: Sun, 19 Oct 2008 18:12:12 GMT\r\nServer: Apache\r\nExpires: Tue, 27 Apr 1971 19:44:06 EST\r\nCache-Control: no-cache\r\nConnection: close\r\nTransfer-Encoding: chunked\r\nContent-Type: text/plain\r\n\r\n0\r\n\r\n'

Alguem conhece uma forma simples de enviar headers assim como o fnds fez mas sem ter que escrever um script?

Em tempos li uma forma que envolvia o uso de telnet mas já não me lembro. A libcurl é fie e permite ver os headers da resposta facilmente e mudar os headers do pedido mais ou menos facilmente... mas fixe fixe era escrever mesmo o pedido manualmente, sem  complicações.

Não estou a perceber o teu problema, "escrever mesmo o pedido manualmente, sem  complicações"?
0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Alguem conhece uma forma simples de enviar headers assim como o fnds fez mas sem ter que escrever um script?

Em tempos li uma forma que envolvia o uso de telnet mas já não me lembro.

Qual é o problema do telnet?

Mas também podes usar o netcat ( http://www.rootr.net/man/info/netcat ).

$ cat conn.txt

GET / HTTP/1.1
Host: google.com

$ sed "-es/$/\r/" conn.txt | nc google.com 80

HTTP/1.1 301 Moved Permanently
Location: http://www.google.com/
Content-Type: text/html; charset=UTF-8
Date: Sun, 19 Oct 2008 18:30:39 GMT
Expires: Tue, 18 Nov 2008 18:30:39 GMT
Cache-Control: public, max-age=2592000
Server: gws
Content-Length: 219

<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Dá 400 porque o youtube requer o envio do User Agent. Resolvido!

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

pmg, não é problema nenhum eu é que não me lembrava como o usar.

Mas estive a experimentar e é trivial.

Basta escrever:

telnet host porta

e depois escrever o pedido manualmente. Isto é porreiro porque dá para fazer debugging de servidores.

p@p-laptop:~$ telnet google.com 80
Trying 64.233.187.99...
Connected to google.com.
Escape character is '^]'.
GET /
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>302 Moved</TITLE></HEAD><BODY>
<H1>302 Moved</H1>
The document has moved
<A HREF="http://www.google.se/">here</A>.
</BODY></HTML>
Connection closed by foreign host.

Sem complicações estva eu a dizer, porque se quero ter 100% de controlo do meu pedido não há nada melhor de que simplesmente escreve-lo. Entre usar a libcurl, recorrer a uma linguagem de programação e abrir e ler de sockets manualmente, ou usar o cat, sed, netcat, acho que é sempre menos pratico do que simlesmente escrever o header e clicar enter. Mas isto tambem já aqui estamos a dicutir promenorzitos que não interessam ao menino jesus.

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Só mais um pormenorzito que nem interessa ao menino jesus:

Com o netcat podes redireccionar o input para um ficheiro e escusas de estar sempre a escrever o pedido à mão.

Suponho que isto é impossível (agora não posso testar) com o telnet ...

nc google.com 80 < pedido.txt
telnet google.com 80 < pedido.txt

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Podes usar um pipe por exemplo

cat pedido.txt | telnet google.com 80

0

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!


Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.


Entrar Agora