Javascript-форум (https://javascript.ru/forum/)
-   Node.JS (https://javascript.ru/forum/node-js-io-js/)
-   -   Node не открывает картинку (https://javascript.ru/forum/node-js-io-js/74062-node-ne-otkryvaet-kartinku.html)

vdekameron 09.06.2018 15:26

Node не открывает картинку
 
Добрый день. Продолжаю изучать Node. По запросу пользователя http://localhost:3000/index.html?secret=o_O хочу выдавать ему простейшую страницу html состоящую из заголовка и картинки. Но через node страница загружается без картинки(((. А если просто эту страницу открываю в браузере то все норм.
Подскажите, пожалуйста, что я делаю не так?
var http = require('http');
var url = require('url');
var path = require('path');
var fs = require('fs');
 
var ROOT = __dirname + "\\deep";
 
var server = http.createServer();
 
server.on('request', function(req, res) {
    if (!checkAccess(req)) {
        res.statusCode = 403;
        res.end("Tell me the secret to access!");
        return;
    };
 
    var filePath = path.normalize(path.join(ROOT, url.parse(req.url).pathname));
    
    fs.readFile(filePath, function(err, content) {
        if (err) throw err;
 
        var mime = require('mime').getType(filePath);
        res.setHeader('Content-Type', 'text/html; charset=utf-8');
        res.end(content);
    });
 
}).listen(3000);
 
function checkAccess(req) {
    return url.parse(req.url, true).query.secret == 'o_O';
};


Вот страница которую пользователь пытается загрузить.

Код:

<!DOCTYPE html>
<html>
<head>
    <title>My page</title>
 
    <!-- meta tags -->
    <meta charset="UTF-8">
    <meta name="description" content="">
    <meta name="keywords" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
 
    <!-- style links -->
    <link rel="shortcut icon" href="" type="image/x-icon">
    <link rel="stylesheet" href="">
 
    <!-- script link -->
    <script src="" type="text/javascript"></script>
 
    <!-- [if lt IE 9] >
    <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif] -->
</head>
<body>
    <h1>Hi this is my first page!</h1>
    <img src="ball.png" alt="ball">
    <!-- Live reload -->
    <script>document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] + ':35729/livereload.js?snipver=1"></' + 'script>')
    </script>
</body>
</html>


Audaxviator 12.06.2018 10:13

Ну потому что атрибут src в теге img - это отдельный GET-запрос браузера к серверу. Соответственно, он и должен быть обслужен - как отдельный GET-запрос.
Типа:
if(req.url == '/ball.png') {
  fs.readFile(__dirname + req.url, function(err, file) {
    res.setHeader('Content-Type', 'image/png');
    res.end(file);
  });
}

vdekameron 12.06.2018 21:12

Не могли бы вы показать как поправить мой код. У меня ведь req.url == '/index.html' Который в свою очередь подтягивает уже картинку.
А если в index.html таких картинок 100, что для каждой картинки делать
if(req.url == '/ball.png')........ Непонятно как то.

Audaxviator 13.06.2018 06:54

Данный "учебный пример" (для понимания некоторых общих принципов взаимодействия браузеров с серверами) примерно так:
var http = require('http');
var fs = require('fs');
var url = require('url');

http.createServer(function(req, res) {
	
  var urlParse = url.parse(req.url, true);
	
  if(urlParse.pathname == '/index.html' && checkAccess(req)) {
    console.log(req.url);
    fs.readFile(__dirname + '/index.html', function(err, content) {
      if(err) console.log(err);
      res.end(content);
    });
  }else if(req.url == '/ball.png') {
    console.log(req.url);
    fs.readFile(__dirname + req.url, function(err, file) {
      if(err) console.log(err);
      res.setHeader('Content-Type', 'image/png');
      res.end(file);
    });
  }else{
    res.statusCode = 403;
    res.end("Tell me the secret to access!");
  }
	
}).listen(3000, () => console.log('On PORT 3000'));

function checkAccess(req) {
	return url.parse(req.url, true).query.secret == 'o_O';
}

А вообще, см. камент выше - так статику, конечно, не выдают (хоть одна картинко, хоть 100).
Ну и в целом, pathname в Node.js (и не только в Node.js, ну да ладно) - это просто строка, произвольный набор символов (нопремер, набор символов "/index.html", который можно заменить на набор "/asadsfghjk" - и всё будет работать так же), никакого указания на пути или файлы она в себе не несёт.

vdekameron 14.06.2018 14:16

Ну все получилось. Принцип я понял. Но я все же не понимаю одного - если в html появится например ball1.png то сервер его не загрузит пока мы не пропишем в сервере
else if(req.url == '/ball1.png') {//.......

Это же не логично! Объясните пожалуйста как быть в таком случае.

Alexandroppolus 14.06.2018 15:22

Цитата:

Сообщение от vdekameron
Это же не логично! Объясните пожалуйста как быть в таком случае.

как это не логично? всё логично

нода - это не апач для пхп, например. Здесь "из коробки" вообще нет никакого вебсервера за кадром, потому никто и не отдаст картинку вместо тебя. Всё что вручную прописал, то и будет отправлено. Даже ошибки типа 404 надо вручную отправлять )

сложно, зато максимальная гибкость. А так - обычно берут какой-нибудь express, например, и там есть модуль для статики, который просто подключаешь и он работает. Ну или можно свой написать, если есть настроение. Который просто берет путь из url, и по этому пути забирает файл из некоторой заранее определенной папки, в которой лежит статика. Если файла нет, то отдает 404. И тогда достаточно будет закинуть файл в эту папку, не понадобится специально для каждого файла свой if в коде (вообще это всё так, поиграться, потому как на больших проектах статика вообще лежит на отдельном сервере и выдается нгинксом)

Audaxviator 14.06.2018 15:56

Вот, можешь добавлять в index.html 100500 картинок, а так же сделать ещё 100 *.html с 500 картинок в каждом, и делать на них ссылки (атрибут href - это тоже GET-запрос).
var http = require('http')
	, nodeStatic = require('node-static')
	, static = new nodeStatic.Server('.', { cache: 0 })
	, url = require('url');

function foo(req, res) {
	
	var urlParse = url.parse(req.url, true);
	
	if(checkAccess(req)) {
		req.url = urlParse.pathname;
		static.serve(req, res);
		return;
	}
	
  static.serve(req, res);
}

http.createServer(foo).listen(3000, function() {
	console.log('PORT = 3000');
});

function checkAccess(req) {
	return url.parse(req.url, true).query.secret == 'o_O';
};

Короче, сервер для такого сайта - http://mongoosejs.com - готов.

Но вообще-то, чтобы отдавать на GET-запросы html-страницы с картинками, ни Node.js, ни какая другая платформа - не нужны. Нопремер Nginx с этим легко справится в одиночку.
Короче, возьми хороший учебничек Итана Брауна и не парься.

vdekameron 14.06.2018 20:34

Цитата:

Сообщение от Audaxviator
Короче, возьми хороший учебничек Итана Брауна и не парься.

Это учебник по node.js? Я давно ищу доступный для понимания подробный учебник по node.js но как-то пока ни какому душа не легла. Все как-то скучно, заумно.

Спасибо вам за терпение. Чет не впирается мне этот node. Думал он попроще)))

vdekameron 15.06.2018 09:46

Не могу понять почему вот так картинки не загружаются

var http = require('http');
var static = require('node-static');
var url = require('url');

var file = new static.Server('./deep', {cache:0});

var server = http.createServer();

server.on('request', function(req, res) {
	var urlParse = url.parse(req.url, true);

	if(!checkAccess(req)) {
		res.statusCode = 403;
  	res.end("Tell me the secret to access!");
  	return;
	};

	if(checkAccess(req)) {
		req.url = urlParse.pathname;
		file.serve(req, res);
		return;
	};

	file.serve(req, res);
});

server.listen(3000, function() {
	console.log('Port-3000');
});

function checkAccess(req) {
	return url.parse(req.url, true).query.secret == 'o_O';
};

Audaxviator 15.06.2018 10:36

Потому что надо убрать все return - после return жизни нет.

Audaxviator 15.06.2018 11:13

Хотя, надо ещё и конкретный url с "секретом" оговаривать
server.on('request', function(req, res) {
	var urlParse = url.parse(req.url, true);

	if(urlParse.pathname == '/index.html' && !checkAccess(req)) {
		res.statusCode = 403;
		res.end("Tell me the secret to access!");
	};
	if(urlParse.pathname == '/index.html' && checkAccess(req)) {
		req.url = urlParse.pathname;
		file.serve(req, res);
	};

	file.serve(req, res);
});

stweet 15.06.2018 11:32

Вот принцип работы любого вебсервера.
let http = require('http');
let fs = require('fs');

// access dirictory static files
let filesRoot = __dirname + '/access';

// allow rule for files
let fileRules = /(png|jpg|gif|html|js|css)$/i;

// allow file mime list
let fileTypes = {
    png:    'image/png', 
    jpg:    'image/jpg', 
    gif:    'image/gif',
    html:   'text/html',
    css:    'text/css',
    js:     'text/javascript'};

// server error handler
function sendError(req, res) {
    // check method for response type
    res.writeHead(404, {'Content-Type': 'text/plain'});
    res.end('Bas request');
}

// server file send handler
function sendFile(req, res) {

    let type = fileRules.exec(req.url);
        type = type.toLocaleString();
    
    // @todo check file or send error
    res.writeHead(200, {'Content-Type': fileTypes[type]});
    res.end(fs.readFileSync(filesRoot + req.url));
}

// server post logic handler
function sendPostData(req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('This is result post request');
}

// server get logic handler
function sendGetData(req, res) {
    if (req.url == '/' || req.url == '/home') {
        res.writeHead(200, {'Content-Type': fileTypes['html']});
        res.end(fs.readFileSync(filesRoot + '/home.html'));
    } else {
        res.writeHead(404, {'Content-Type': fileTypes['html']});
        res.end(fs.readFileSync(filesRoot + '/404.html'));
    }
}

// server logic handler
function sendData(req, res) {
    switch(req.method.toLocaleString()) {
        case 'get': sendGetData(req, res); break;
        case 'post': sendPostData(req, res); break;
        default: sendError(req, res);
    }
}

// server request handler
function onRequestEvent(req, res) {
    if (fileRules.test(req.url)) 
        sendFile(req, res);
    else 
        sendData(req, res);
}

let server = http.createServer();
    server.on('request', onRequestEvent)
    server.listen(process.env.PORT || 8000)

vdekameron 20.06.2018 14:41

Спасибо. Так все получилось.


Часовой пояс GMT +3, время: 13:17.