Ir para o conteúdo
skin

fopen não funciona bem...

Mensagens Recomendadas

skin    0
skin

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;
}

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    102
pmg

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 () ...

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
skin    0
skin

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pedrotuga    31
pedrotuga

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
skin    0
skin

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:

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pedrotuga    31
pedrotuga

É 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

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pedrotuga    31
pedrotuga

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
skin    0
skin

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    102
pmg

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 */
}

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pedrotuga    31
pedrotuga

:)

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 :)

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
fnds    2
fnds

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
djthyrax    11
djthyrax

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pedrotuga    31
pedrotuga

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
fnds    2
fnds

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"?

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    102
pmg

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>

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pedrotuga    31
pedrotuga

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.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
pmg    102
pmg

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

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


×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade